2020.04.22更新:根据用户的反馈,我们现在已支持同步调用。例如cvm 2017-03-12版本的DescribeRegions,如果想同步调用,直接DescribeRegionsSync即可。选用同步调用,请保持所有调用均为同步。同步异步混用,如果没处理好,容易造成问题。
==========原文=================
API 3.0 发布后,配套的多语言SDK将同步更新,其中 .NET SDK 3.0 由微软MVP张善友大大开发。
以下是当前的官网示例:https://cloud.tencent.com/document/sdk/.NET#.E7.A4.BA.E4.BE.8B
在这个例子中,创建的是控制台应用,使用的同步方式调用了异步的接口:
代码语言:txt复制DescribeInstancesResponse resp = client.DescribeInstances(req)
.ConfigureAwait(false).GetAwaiter().GetResult();
有一些朋友在开发ASP和Windows Forms应用时,发现按照官网的使用方式,不能按照预期返回结果,反而会导致界面卡死。
这是因为接口都做了异步化处理,而控制台应用不需要同步上下文,因此这种同步方式调用异步接口是没有问题的,会正常返回。
但是在ASP和Windows Forms应用中,通常不是主线程调用,需要同步上下文,当同步调用异步接口时,会发生UI线程被阻塞,从而界面卡死不动。
要解决这个问题,只需要让UI控件的响应方法异步化就可以了。例如从
代码语言:txt复制private void Button1_Click(object sender, EventArgs e)
改为
代码语言:txt复制private async void Button1_Click(object sender, EventArgs e)
具体的:
代码语言:txt复制 // SDK异步接口
private async Task<string> GetZones()
{
// 处理一些初始化工作
// 发起调用
DescribeZonesResponse resp = await client.DescribeZones(req);
// 输出json格式的字符串回包
return AbstractModel.ToJsonString(resp);
}
// 注意:这里是一个异步接口
private async void Button1_Click(object sender, EventArgs e)
{
textBox1.Text = await GetZones();
}
这里按钮1(Button1)的点击响应方法(Button1_Click)里,异步的调用了.NET SDK接口,以获得可用区的信息,在请求结束后,将得到的返回显示在文本框中。最终的效果类似于:
另外一种方式其实也是用同步的方式,比异步的要差一点,因为UI线程要硬等,直到请求结束前界面都会卡住。具体的,就是将此请求放在一个线程中执行,并等待其结束,再操作UI控件。示例代码如下:
代码语言:txt复制 // SDK异步接口
private async Task<string> GetZones()
{
// 处理一些初始化工作
// 发起调用
DescribeZonesResponse resp = await client.DescribeZones(req);
// 输出json格式的字符串回包
return AbstractModel.ToJsonString(resp);
}
// 注意:这里是一个同步接口
private void Button1_Click(object sender, EventArgs e)
{
var result = "";
var t = Task.Run(() =>
{
// 同步方式调用,会卡住直到请求返回
result = GetZones().ConfigureAwait(false).GetAwaiter().GetResult();
});
// 同步等待,会卡住直到线程返回
t.Wait();
textBox1.Text = result;
}
由于本人.NET编程水平有限,此方案未必是最优的。有需要的朋友可以借鉴下,或者留言探讨下。
附上源码,注意,源码中设置了对.NET SDK的依赖和其他的依赖,使用NuGet可以添加这个依赖。(把依赖一起打包的话包体积在8MB,上传失败了 。。)
另外需要从环境变量中读取一些信息,如果没有这些环境变量,执行会失败。
对此,你可以把自己的密钥写在代码中,或者设置所需要的对应的环境变量。如果是直连环境,可以不设置代理。