试图在.net 4.0中运行任务(使用SSIS)

问题描述 投票:0回答:1

我有一个SSIS包,其中包含一些脚本。其中一个通过REST API获取令牌。

我写了下面的内容,在.net 4.5中正常工作-但是,我们的服务器不是最新的,我们必须降级到.net 4.0,这是我们打h的地方,因为4.0没有GetAwaiter(以及其他各种方便的功能)。

为了增加乐趣,如上所述,这是SSIS,我相信您不能在其中添加NuGet软件包。

    public void Main()
    {
        //read the token from the file
        string ref_token = File.ReadAllText(Dts.Variables["User::PATH_refresh_token"].Value.ToString());
        **Dts.Variables["User::API_returned"].Value = GetToken(Dts.Variables["$Package::API_token_client_id"].Value.ToString(), Dts.Variables["$Package::API_token_client_secret"].Value.ToString(), ref_token, Dts.Variables["$Package::API_token_endpoint"].Value.ToString()).GetAwaiter().GetResult();**
    }

    static async Task<string> GetToken(string client_id, string client_secret, string ref_token, string token_url)
    {
        try
        {
            var client = new System.Net.Http.HttpClient();
            HttpContent content = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("client_id", client_id),
                new KeyValuePair<string, string>("client_secret", client_secret),
                new KeyValuePair<string, string>("grant_type", "refresh_token"),
                new KeyValuePair<string, string>("refresh_token", ref_token),
                new KeyValuePair<string, string>("expiration", "20160")
            });
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
            **var response = await client.PostAsync(token_url, content);**
            var responseString = await response.Content.ReadAsStringAsync();
            return responseString;
        }
        catch (Exception exception)
        {
            return exception.ToString();
        }
    }

所以我们目前在GetAwaiter()上遇到问题(代码的第五行,突出显示):

''Task(string)'不包含'GetAwaiter'的定义...

并且也在此行中等待(也突出显示):

var response = await client.PostAsync(token_url, content);

''Task(HttpResponseMessage)'不包含'GetAwaiter'的定义...

c# .net ssis .net-4.0 .net-4.5
1个回答
1
投票

不幸的是,我尝试连接的一方使用TLS12和TLS11,.net 4.0中不支持。

好吧,然后解决GetAwaiter问题将无济于事。

但为后代:

使用await的任何代码都可以转换为不使用await的等效代码。为此,您需要手动拆分代码,并使用ContinueWith代替await,并使用TaskCompletionSource<T>代替async。无论如何,这大约是what the compiler is doing to your code

逐步:

首先,您需要将async替换为TaskCompletionSource<T>

static Task<string> GetToken(...)
{
  var tcs = new TaskCompletionSource<string>();
  try
  {
    ...
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
    var response = await client.PostAsync(token_url, content);
    var responseString = await response.Content.ReadAsStringAsync();
    return responseString;
  }
  catch (Exception exception)
  {
    return exception.ToString();
  }
}

[所有return语句现在成为设置TCS结果的代码:

static Task<string> GetToken(...)
{
  var tcs = new TaskCompletionSource<string>();
  try
  {
    ...
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
    var response = await client.PostAsync(token_url, content);
    var responseString = await response.Content.ReadAsStringAsync();
    tcs.TrySetResult(responseString);
  }
  catch (Exception exception)
  {
    tcs.TrySetResult(exception.ToString());
  }
}

下一步,删除try / catch(但请记住它在那儿)。使用ContinueWith,我们需要继续处理错误:

static Task<string> GetToken(...)
{
  var tcs = new TaskCompletionSource<string>();
  ...
  ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
  var response = await client.PostAsync(token_url, content);
  var responseString = await response.Content.ReadAsStringAsync();
  tcs.TrySetResult(responseString);
//  catch (Exception exception)
//  {
//    tcs.TrySetResult(exception.ToString());
//  }
}

现在您可以开始将await语句转换为ContinueWith。对于每个方法,将方法的其余部分移至一个继续。请注意ContinueWith is dangerous,因此请确保传递正确的调度程序。该代码看起来好像不需要原始上下文,因此我正在使用ContinueWith。因此,从技术上讲,这是TaskScheduler.Defaultawait的转换,而不仅仅是普通的ConfigureAwait(false),后者会更复杂。

延续得到一个任务,它可以查询异常或结果。注意哪些成员在await中包装了异常;可以更改您的异常处理代码。

这是第一个AggregateException转换的样子:

await

第二个static Task<string> GetToken(...) { var tcs = new TaskCompletionSource<string>(); ... ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls; client.PostAsync(token_url, content).ContinueWith(task => { if (task.IsFaulted) { tcs.TrySetResult(task.Exception.InnerException.ToString()); return; } var response = task.Result; var responseString = await response.Content.ReadAsStringAsync(); tcs.TrySetResult(responseString); }, TaskScheduler.Default); // catch (Exception exception) // { // tcs.TrySetResult(exception.ToString()); // } } 转换可以类似的方式进行:

await

或者,通过简单的static Task<string> GetToken(...) { var tcs = new TaskCompletionSource<string>(); ... ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls; client.PostAsync(token_url, content).ContinueWith(task => { if (task.IsFaulted) { tcs.TrySetResult(task.Exception.InnerException.ToString()); return; } var response = task.Result; response.Content.ReadAsStringAsync().ContinueWith(task2 => { if (task2.IsFaulted) { tcs.TrySetResult(task2.Exception.InnerException.ToString()); return; } var responseString = task2.Result; tcs.TrySetResult(responseString); }, TaskScheduler.Default); }, TaskScheduler.Default); } 语句一个接一个,您可以“链接”延续。您确实需要使用await,因为第一个延续返回任务。这种方法看起来像这样:

Unwrap

作为最后的说明,通过“链式”延续,许多人更喜欢让异常通过并在末尾将它们压平;这样的代码要短一些:

static Task<string> GetToken(...)
{
  var tcs = new TaskCompletionSource<string>();
  ...
  ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
  client.PostAsync(token_url, content).ContinueWith(task =>
  {
    if (task.IsFaulted)
    {
      tcs.TrySetResult(task.Exception.InnerException.ToString());
      return;
    }

    var response = task.Result;
    return response.Content.ReadAsStringAsync();
  }, TaskScheduler.Default)
  .Unwrap()
  .ContinueWith(task =>
  {
    if (task.IsFaulted)
    {
      tcs.TrySetResult(task.Exception.InnerException.ToString());
      return;
    }

    var responseString = task.Result;
    tcs.TrySetResult(responseString);
  }, TaskScheduler.Default);
}

因此,开发人员喜欢static Task<string> GetToken(...) { var tcs = new TaskCompletionSource<string>(); ... ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls; client.PostAsync(token_url, content).ContinueWith(task => { var response = task.Result; return response.Content.ReadAsStringAsync(); }, TaskScheduler.Default) .Unwrap() .ContinueWith(task => { if (task.IsFaulted) { tcs.TrySetResult(task.Exception.Flatten().InnerException.ToString()); return; } var responseString = task.Result; tcs.TrySetResult(responseString); }, TaskScheduler.Default); } async关键字。 ;)

© www.soinside.com 2019 - 2024. All rights reserved.