我有一个需要在单公寓线程上下文中进行的调用,但我不能保证在我的代码中设置[STAThread]
因为我不控制入口点和我的代码将通过反思来调用。
我想出了这种调用调用并返回令牌的方法,但我希望有更好的方法:
private static string token;
private static Task<string> GetToken(string authority, string resource, string scope) // I don't control this signature, as it gets passed as a delegate
{
Thread t = new Thread(GetAuthToken);
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
return Task.Run(() =>
{
return token;
});
}
private static void GetAuthToken()
{
Credentials creds = AuthManagement.CreateCredentials(args); // this call must be STA
token = creds.Token;
}
我的约束:
Task<string> MyMethod(string, string, string)
AuthManagement.CreateCredentials(args)
必须在单线程公寓环境中调用我需要调用该方法,使其保证为STA,并返回结果。
感谢您的帮助!
答案 0 :(得分:2)
有一种更好的方法。您必须创建一个新线程以保证您在STA线程上,因为您无法在启动后更改线程的公寓状态。但是,您可以摆脱Thread.Join()
调用,以便使用TaskCompletionSource实际异步您的方法:
private static async Task<string> GetToken(string authority, string resource, string scope) // I don't control this signature, as it gets passed as a delegate
{
using (var tcs = new TaskCompletionSource<string>()) {
Thread t = new Thread(() => GetAuthToken(tcs));
t.SetApartmentState(ApartmentState.STA);
t.Start();
var token = await tcs.Task
return token;
}
}
private static void GetAuthToken(TaskCompletionSource<string> tcs)
{
try {
Credentials creds = AuthManagement.CreateCredentials(args); // this call must be STA
tcs.SetResult(creds.Token);
}
catch(Exception ex) {
tcs.SetException(ex);
}
}
此外,如果您需要在任务中包含返回值,请使用Task.FromResult()
代替Task.Run()
。