在单线程公寓中运行代码并返回值,其中我不能设置当前公寓模型

本文关键字:公寓 不能 设置 模型 返回值 运行 单线程 代码 | 更新日期: 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;
    }

我的约束:

    第一个方法的签名必须Task<string> MyMethod(string, string, string)
  • AuthManagement.CreateCredentials(args) 必须在单线程公寓上下文中调用
  • 当前线程上下文不能保证为STA,因此应假定为MTA。

我需要以这样一种方式调用该方法,保证它是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()