如何在 Visual Studio 中将 RingCentral SMS 控制台应用程序转换为表单应用程序?

How to convert RingCentral SMS console app to a Forms app in Visual Studio?

我需要从我的 VB.net Windows Forms 应用发送短信。 RingCentral 文档在 C# 中提供了一个控制台应用程序示例,使用 InstantVB 将其转换为 VB.net 相当简单。下面的代码可以正常工作,因为它是从他们的 C# 示例直接翻译而来的,但它仍然是一个控制台应用程序。 (哦,他们的例子有一个我必须修复的错误。RINGCENTRAL_PRODUCTION 应该是布尔值 False,而不是他们的例子中的字符串“False”。)

无论如何...我一直在尝试 运行 在 Windows 表单应用程序中使用类似的代码。 当然,我没有 Forms 应用程序的 Sub Main。所以我尝试将该代码放入 Form.Load 事件中。但是当这样做时,它总是挂在授权行上,没有错误消息——它只是挂起,直到我单击 IDE.[=24 中的“暂停”(中断)按钮=]

我整天都在研究这个问题,在线搜索答案,非常感谢任何指导。

Imports System
Imports System.Threading.Tasks
Imports RingCentral

Namespace Send_SMS
    Friend Class Program
        Private Const RECIPIENT As String = "9165551212"
        Private Const RINGCENTRAL_CLIENTID As String = "_not_my_real_client_ID"
        Private Const RINGCENTRAL_CLIENTSECRET As String = "_not_my_real_client_secret_"
        Private Const RINGCENTRAL_PRODUCTION As Boolean = False

        Private Const RINGCENTRAL_USERNAME As String = "+14245551212"
        Private Const RINGCENTRAL_PASSWORD As String = "notarealpassword"
        Private Const RINGCENTRAL_EXTENSION As String = "101"

        Private Shared restClient As RestClient

        Shared Sub Main(ByVal args() As String)
            restClient = New RestClient(RINGCENTRAL_CLIENTID, RINGCENTRAL_CLIENTSECRET, RINGCENTRAL_PRODUCTION)

            restClient.Authorize(RINGCENTRAL_USERNAME, RINGCENTRAL_EXTENSION, RINGCENTRAL_PASSWORD).Wait()
            send_sms().Wait()
        End Sub

        Private Shared Async Function send_sms() As Task
            Dim parameters = New CreateSMSMessage()
            parameters.from = New MessageStoreCallerInfoRequest With {.phoneNumber = RINGCENTRAL_USERNAME}
            parameters.to = New MessageStoreCallerInfoRequest() {
                New MessageStoreCallerInfoRequest With {.phoneNumber = RECIPIENT}
            }
            parameters.text = "Hello World from VB.net" '< I changed that part.
            Dim resp = Await restClient.Restapi().Account().Extension().Sms().Post(parameters)
            Console.WriteLine("SMS sent. Message status: " & resp.messageStatus)
        End Function


    End Class
End Namespace

仅供参考,以下为C#原文(修正了bug):

using System;
using System.Threading.Tasks;
using RingCentral;

namespace Send_SMS
{
    class Program
    {
        const string RECIPIENT = "9165551212";
        const string RINGCENTRAL_CLIENTID = "_not_my_real_client_ID";
        const string RINGCENTRAL_CLIENTSECRET = "_not_my_real_client_secret_";
        const Boolean RINGCENTRAL_PRODUCTION = false;

        const string RINGCENTRAL_USERNAME = "+14245551212";
        const string RINGCENTRAL_PASSWORD = "notarealpassword";
        const string RINGCENTRAL_EXTENSION = "101";

        static RestClient restClient;

        static void Main(string[] args)
        {
            restClient = new RestClient(RINGCENTRAL_CLIENTID, RINGCENTRAL_CLIENTSECRET, RINGCENTRAL_PRODUCTION);

            restClient.Authorize(RINGCENTRAL_USERNAME, RINGCENTRAL_EXTENSION, RINGCENTRAL_PASSWORD).Wait();
            send_sms().Wait();
        }
        static private async Task send_sms()
        {
            var parameters = new CreateSMSMessage();
            parameters.from = new MessageStoreCallerInfoRequest { phoneNumber = RINGCENTRAL_USERNAME };
            parameters.to = new MessageStoreCallerInfoRequest[] { new MessageStoreCallerInfoRequest { phoneNumber = RECIPIENT } };
            parameters.text = "Hello World from C#";

            var resp = await restClient.Restapi().Account().Extension().Sms().Post(parameters);
            Console.WriteLine("SMS sent. Message status: " + resp.messageStatus);
        }
    }
}

表单应用程序和控制台应用程序之间没有任何神奇的区别..

创建一个新的表单应用程序(它有一个名为 Form1 的表单,在表单上放置一个按钮并保留默认名称 Button1 [但保证你稍后会更改它]),右键单击项目解决方案资源管理器中的节点并选择管理 Nuget 包,浏览 RingCentral.Net 包并安装它

将此代码粘贴到 Form1.vb 代码中所有内容的顶部:

Imports RingCentral

Public Class Form1
    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        restClient = New RestClient(RINGCENTRAL_CLIENTID, RINGCENTRAL_CLIENTSECRET, RINGCENTRAL_PRODUCTION)

        Await restClient.Authorize(RINGCENTRAL_USERNAME, RINGCENTRAL_EXTENSION, RINGCENTRAL_PASSWORD)
        Await send_sms()

    End Sub

    Private Const RECIPIENT As String = "9165551212"
    Private Const RINGCENTRAL_CLIENTID As String = "_not_my_real_client_ID"
    Private Const RINGCENTRAL_CLIENTSECRET As String = "_not_my_real_client_secret_"
    Private Const RINGCENTRAL_PRODUCTION As Boolean = False

    Private Const RINGCENTRAL_USERNAME As String = "+14245551212"
    Private Const RINGCENTRAL_PASSWORD As String = "notarealpassword"
    Private Const RINGCENTRAL_EXTENSION As String = "101"

    Private Shared restClient As RestClient



    Private Shared Async Function send_sms() As Task
        Dim parameters = New CreateSMSMessage()
        parameters.from = New MessageStoreCallerInfoRequest With {.phoneNumber = RINGCENTRAL_USERNAME}
        parameters.to = New MessageStoreCallerInfoRequest() {
                New MessageStoreCallerInfoRequest With {.phoneNumber = RECIPIENT}
            }
        parameters.text = "Hello World from VB.net" '< I changed that part.
        Dim resp = Await restClient.Restapi().Account().Extension().Sms().Post(parameters)
        Console.WriteLine("SMS sent. Message status: " & resp.messageStatus)
    End Function

End Class

当然,我得到一个异常,因为代码中的细节是伪造的,但这至少是服务的响应!


奖励:等待和任务 101:

可以等待 return 任务的方法(functions/subs)。包含 await 关键字的方法需要在其代码正文中标记为 async。如果您 运行 一个 return 是 Task(Of X) 的方法,您应该很快得到一个 Task(Of X) 返回,而 运行 时间开始处理任务。您可以设想,现在 Task 是一个空容器,当 Task 完成时将用 X 填充。如果你想要里面的 Xawait 会等待任务完成,然后为你拉出 X; “当 X 准备好时,等待将 Task(Of X) 转换为 X”。当你的程序的线程正在 await 发生时,它会回到它之前所做的任何事情(绘制 UI 可能)这很好,因为它使你的应用程序看起来没有挂起。

你应该注意到,这有点像当朋友来喝咖啡时保存你的电脑游戏并关闭电脑(这个任务需要一段时间) - 朋友走了,你回到游戏,重新加载保存的状态和一切都是原样。您的程序进入等待状态,保存游戏并继续做其他事情。任务完成后返回,重新加载游戏,并从中断处继续

您会注意到 Task(Of X) 还有其他东西,例如 Result 属性。如果您访问它而不是等待,那么您的程序将在任务完成时卡住,然后您将获得 X。在控制台应用程序中这可能无关紧要,因为控制台应用程序可能不会做任何其他事情在此期间,但是 UI 应用程序需要绘制它的 UI 否则 windows 会认为它没有响应。

我以 Task(Of X) 开头,因为它可能更容易理解“一项需要花费一段时间才能完成的任务,然后会给我想要的东西”。对于 return 一个 Task 的方法(即任务中没有输出对象),您只需 Await 它们,然后它们就完成了。 Await 没有挖掘出任何结果对象,因为没有,但您的程序仍然能够绘制它的 UI。在 Task 上调用 Wait() 也会等待它完成,但它会在它完成时阻塞你的 UI