是否可以确定方法是同步还是异步?

时间:2018-03-21 00:02:48

标签: c# .net asynchronous async-await

假设我使用了一个我无法访问其源代码的库,并且它具有以下方法之一:我将其称为类型A,B和C

A型:

public async Task FakeAsyncMethod1()
{
    await Task.Run(() =>
    {
        // Some synchronous CPU-bound work.
        Thread.Sleep(1000);
    });
}

B类:

public async Task<string> FakeAsyncMethod2()
{
    string result = await Task.Run(() =>
    {
        // Some synchronous IO-bound work.
        var request = (HttpWebRequest)WebRequest.Create("someURL");
        using (var stream = request.GetResponse().GetResponseStream())
        using (var reader = new StreamReader(stream))
        {
            return reader.ReadToEnd();
        }
    });
    return result;
}

C型:

public async Task<string> RealAsyncMethod()
{
    HttpClient client = new HttpClient();
    // Some asynchronous IO-bound work.
    var responseMsg = await client.GetAsync("someURL");
    return await responseMsg.Content.ReadAsStringAsync();
}

现在,我并不期望能够区分A型和B型。它们都在Task.Run中包含了一些同步工作,我认为它不受CPU限制或IO绑定的影响。

所以,我的问题是:

如果库的开发人员使用了type-A或type-B,那么这将是一个非常糟糕的实现,是否有办法判断一个方法是否是C型(完全异步)?

另外,假设我们有一个类似于B型(或A)的方法,但阻塞代码甚至不包含在Task.Run中,有没有办法确定它是阻塞方法(阻止当前线程)?当然,我可以手动检查它是否阻止了UI线程(例如,在WinForms应用程序中),但我想知道是否有更好的方法来做到这一点(也许, 编程 )。

编辑:我没有寻找涉及分析代码的解决方案(例如,可以建议使用反编译器等)。有时源代码甚至可用,但我不会因为某种原因检查它。

我正在寻找的是通过运行代码并分析其行为来直接解决问题的方法(例如,分析线程等,我不知道如何),我想知道这是否可能。

1 个答案:

答案 0 :(得分:0)

我不是100%确定我在下面所说的内容,但即使错误或不完整也可能是一个很好的起点。

由于方法A和方法B阻塞线程池的线程(虽然完全异步方法没有),只要你控制进程创建的线程,就可以在不同的时间比较线程池中的可用线程T1 T2。

我创建了一个简单的例子:

static void Main(string[] args)
{
    var t = MainAsync(args);

    t.Wait();

    Console.ReadKey();
}

static async Task MainAsync(string[] args)
{
    int availableThreadT1;
    int availableAsyncIOThreadT1;

    int availableThreadT2;
    int availableAsyncIOThreadT2;          

    ThreadPool.GetAvailableThreads(out availableThreadT1, out availableAsyncIOThreadT1);

    //var t1 = FakeAsync(); //Locked thread 1
    var t2 = RealAsync(); //Locked thread 0

    ThreadPool.GetAvailableThreads(out availableThreadT2, out availableAsyncIOThreadT2);

    //Console.Write($"Locked threads from FakeAsync {availableThreadT1 - availableThreadT2} \r\n");
    Console.Write($"Locked threads from RealAsync {availableThreadT1 - availableThreadT2} \r\n");
}

static async Task FakeAsync()
{

    var t = Task.Run(() => 
    {
        Thread.Sleep(1000);
    });


    await t;

}

static async Task RealAsync()
{

    var t = Task.Delay(1000);

    await t;

}