基于API3.0开发C# Windows Forms应用

2020-04-22 16:28:07 浏览数 (1)

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接口,以获得可用区的信息,在请求结束后,将得到的返回显示在文本框中。最终的效果类似于:

image.pngimage.png

另外一种方式其实也是用同步的方式,比异步的要差一点,因为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,上传失败了 。。)

另外需要从环境变量中读取一些信息,如果没有这些环境变量,执行会失败。

对此,你可以把自己的密钥写在代码中,或者设置所需要的对应的环境变量。如果是直连环境,可以不设置代理。

WindowsFormsApp1.zip

0 人点赞