C# 与UI同步使用异步函数

C# 与UI同步使用异步函数,c#,asynchronous,task-parallel-library,webbrowser-control,live-sdk,C#,Asynchronous,Task Parallel Library,Webbrowser Control,Live Sdk,我有一个应用程序(WinForms)。它只需抓取一些数据,对其进行一些处理,然后将结果上传到一些云存储。我现在使用一些第三方代码来处理云存储的身份验证。此代码将创建一个WinForm,它承载一个浏览器控件,如果用户尚未提供应用程序使用云存储的凭据和权限,则会弹出该控件。在我的程序开始运行之前,我想确保我已经通过了身份验证,因此在程序(program.cs)的Main()循环中,我想使用第三方库对云存储进行身份验证,并阻止我的实际代码(//myCode)执行,直到完成为止。”不幸的是,这个库是异步

我有一个应用程序(WinForms)。它只需抓取一些数据,对其进行一些处理,然后将结果上传到一些云存储。我现在使用一些第三方代码来处理云存储的身份验证。此代码将创建一个WinForm,它承载一个浏览器控件,如果用户尚未提供应用程序使用云存储的凭据和权限,则会弹出该控件。在我的程序开始运行之前,我想确保我已经通过了身份验证,因此在程序(program.cs)的Main()循环中,我想使用第三方库对云存储进行身份验证,并阻止我的实际代码(//myCode)执行,直到完成为止。”不幸的是,这个库是异步的,我花了今天大部分时间试图获得我刚才描述的行为——我的问题实际上是“使异步函数同步”,但我看到的一般答案似乎对我不起作用

所以我有类似的东西

static void Main(string[] args)
{
OAuth.LoginAuthAsync("clientID", "client_secret", ...) 
//Don't want to get here until LoginAuthAsync is done 
application.run(myForm); //myCode
}
但这将弹出web浏览器并运行我的代码,我只希望在web OAuth.LoginAuthAsync完成后才能执行

我不是整个TPL库的专家,但我花了一段时间研究我认为应该有效但不可行的东西。我试过:

我试过了

        Task.Run(async () =>
            {
                OAuth.LoginAuthAsync("123456", "asdasd", ...));
    ).Wait();
在第三方库中抛出一个错误

System.Threading.ThreadStateException:无法实例化ActiveX控件“8856f961-340a-11d0-a96b-00c04fd705a2”,因为当前线程不在单线程单元中。 位于System.Windows.Forms.WebBrowserBase..ctor(字符串clsidString) 在System.Windows.Forms.WebBrowser..ctor()中

于是我试着

        Thread tx = new Thread(() => OAuth.LoginAuthAsync("123456","asdasd", ……..));
        tx.SetApartmentState(ApartmentState.STA);
        tx.Start();
        tx.Join();
但这只是弹出窗口,它立即消失,//myCode执行

任何人都知道我在这里能做什么。我尝试将该方法移动到myForm\u Load事件(即从application.run调用的myForm)中,但我遇到了同样的问题

非常感谢


另外,我不想再使用任何第三方库

您可以使用从
OAuth.LoginAuthAsync
返回的
任务上的
wait()
方法阻止并等待代码完成。这在控制台应用程序中有效,但在GUI/ASP应用程序中可能会导致错误

static void Main(string[] args)
{
    OAuth.LoginAuthAsync("clientID", "client_secret", ...).Wait();

    //Don't want to get here until LoginAuthAsync is done 
    application.run(myForm); //myCode
}
对于GUI应用程序,最好使相关方法
async
,然后
等待调用
OAuth.LoginAuthAsync
,但是
Main
不能是
async
。如果将该方法移动到
myForm\u Load
方法中,您应该能够执行
wait
调用:

public async void myForm_Load(object o, EventArgs e)
{ 
     await OAuth.LoginAuthAsync("clientID", "client_secret", ...);
}

在我看来,这是更好的解决方案。

当您“完成”登录时,是否可以捕获该事件并将其抛出,然后调用join?也可以在调用应用程序之前将其放入应用程序启动中。运行(您的表单)检查。感谢您的回复。不幸的是,第一种方法导致GUI死锁(只是一个带有等待光标的空白表单)。第二种方法也不起作用-在打开登录窗口(而不是我所追求的对话行为)的同时,继续正常执行。弹出一个对话框,然后在该对话框的
Load
事件处理程序中调用
OAuth.LoginAuthAsync