同步使用异步功能与UI

时间:2015-02-23 02:58:31

标签: c# asynchronous task-parallel-library webbrowser-control live-sdk

我有一个应用程序(WinForms)。它只是抓取一些数据,对其进行处理,然后将结果上传到某个云存储。我现在正在使用一些第三方代码来处理我对云存储的身份验证。此代码将创建一个WinForm,它托管一个浏览器控件,如果用户尚未提供应用程序使用云存储的凭据和权限,则会弹出该控件。在我的程序运行之前,我想确保我已经过身份验证,因此在程序的Main()循环中(Program.cs),我想使用第三方库来验证云存储并阻止我的实际代码(// 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(String clsidString)    在System.Windows.Forms.WebBrowser..ctor()

然后我尝试了

        Thread tx = new Thread(() => OAuth.LoginAuthAsync("123456","asdasd", ……..));
        tx.SetApartmentState(ApartmentState.STA);
        tx.Start();
        tx.Join();

但只是弹出窗口,它会立即消失,并且// myCode会执行。

任何机构都有任何想法,我可以在这里做什么。我尝试在 myForm _Load 事件中移动该方法(从application.run调用了myForm),但我遇到了同样的问题。

非常感谢

P.S。我不想使用任何其他第三方库。

1 个答案:

答案 0 :(得分:1)

您可以使用Wait()Task返回的OAuth.LoginAuthAsync方法阻止并等待代码完成。这适用于控制台应用程序,但可能会导致GUI / ASP应用程序中出现deadlock

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然后await调用OAuth.LoginAuthAsync,但Main不能async }。如果您在myForm_Load方法中移动方法,则应该可以await进行调用:

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

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