1

我有 C# avalonia应用程序通过开发人员提供的 SDK 使用了一些非线程安全的库。更具体地说是Windows Zoom SDK。一些 SDK 功能是基于事件驱动模式构建的。调用 SDK 方法后,应用程序必须等待执行结果回调到达。因此,使用 TaskCompletionSource 在应用程序中应用了基于任务的异步模式(请参见下面的代码)。

在应用程序中应用 async/await 模式后,SDK 无法正常工作(详情)。但是,这个问题没有讨论使用 Zoom SDK。问题是关于 async/await 模式的使用如何可能导致某些非线程安全库(或 SDK)的错误行为?

SDK包装方法:

public async Task<bool> SdkMethodAAsync(string parameter)
{
    try
    {
        this.sdkService.SdkMethodA(parameter);

        this.tcs = new TaskCompletionSource<bool>();
        return await this.tcs.Task;
    }
    catch (Exception)
    {
        return false;
    }
    
    return false;
    }

SDK 回调处理程序:

    public void OnMethodAReturn(MethodAResult ret)
    {
        // here some property can also be changed 
        // and which will trigger an event on which SDK calls can be made to         

        this.tcs.TrySetResult(ret == MethodAResult.METHODA_SUCCESS);
    }

高级代码:

    public async Task StartAsync(string parameter1, string parameter2)
    {
        var resultMethodA = await SdkMethodAAsync(parameter1);
        var resultMethodB = await SdkMethodBAsync(parameter2);
    }
4

1 回答 1

0

第一个明显的问题是在进行方法调用后更新任务完成源。该方法可能会同步完成,这会打乱您的模式。将其更改为

    this.tcs = new TaskCompletionSource<bool>();
    this.sdkService.SdkMethodA(parameter);        
    return await this.tcs.Task;

您可能想要防止的另一件事是并发调用。说有人试图做

    var mA = SdkMethodAAsync(parameter1);
    var mB = SdkMethodBAsync(parameter2);
    await Task.WhenAll(mA, mB);

如果 SDK 不允许并发调用,这将是一个错误,但是否会报告错误,或者它是否会导致意外行为并不明显。所以你可能想建立一些机制来检测这样的情况并以某种方式处理它。

另一件可能不明显的事情

this.tcs.TrySetResult(ret == MethodAResult.METHODA_SUCCESS);

这将使任务总是成功,返回值告诉它是否真的成功。我本来希望根据方法结果将任务置于成功/失败/取消状态。这也可能允许返回值或错误消息,而不是简单地成功/失败。

于 2021-05-19T15:01:46.947 回答