在单线程公寓中运行代码并返回值,其中我不能设置当前公寓模型
本文关键字:公寓 不能 设置 模型 返回值 运行 单线程 代码 | 更新日期: 2023-09-27 18:07:10
我有一个需要在单公寓线程上下文中进行的调用,但是我不能通过在代码中设置[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;
}
我的约束:
- 第一个方法的签名必须是
-
AuthManagement.CreateCredentials(args)
必须在单线程公寓上下文中调用 - 当前线程上下文不能保证为STA,因此应假定为MTA。
Task<string> MyMethod(string, string, string)
我需要以这样一种方式调用该方法,保证它是STA,并返回结果。
谢谢你的帮助!
有一个稍微好一点的方法。您必须创建一个新线程以保证您在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()
。