我有一个应用程序(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。我不想使用任何其他第三方库。
答案 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", ...);
}
在我看来,这是更好的解决方案。