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

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

我写了下面的内容,在.net 4.5中可以正常工作-但是,我们的服务器不是最新的,我们必须降级到.net 4.0,这是我们开始打ic的地方,因为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),string>("grant_type","refresh_token"),string>("refresh_token",ref_token),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()中遇到了问题(代码的第五行,突出显示了):

  

“任务(字符串)”不包含“ Getawaiter”的定义...

在这一行中也要等待(也突出显示):

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

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

TOTTI128 回答:尝试在.net 4.0中运行任务(使用SSIS)

  

不幸的是,我尝试连接的一方使用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,因此请确保传递正确的调度程序。这段代码看起来好像不需要原始上下文,因此我正在使用TaskScheduler.Default。因此,从技术上讲,这是awaitConfigureAwait(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);
}

这就是为什么开发人员喜欢asyncawait关键字的原因。 ;)

本文链接:https://www.f2er.com/2952822.html

大家都在问