繁体   English   中英

异步运行同步方法的正确方法是什么

[英]What is the correct way to run synchronous method in asynchronously

我有一个抽象类,其方法定义如下

public abstract class FooBase : IDisposable
{
    protected abstract bool GetData(params object[] getDataParams);
}

我正在使用这样的抽象类,并尝试异步运行GetData方法

public class SomeClass : FooBase
{
    protected override bool GetData(params object[] getDataParams)
    {
        var task = Task.Factory.StartNew(() =>
        {
            using (var adapter = new DataAdapter())
            {
                // Take your time and fetch the data
            }
        });
        task.Wait();
        return true;
    }
}

我试图找出的是:我是对还是错,或者是否有其他更好的方法来实现相同的目标。

更新

如果我这样更改我的方法,它将被异步调用还是不异步调用

public class SomeClass : FooBase
{
    protected override bool GetData(params object[] getDataParams)
    {
        var task = Task.Factory.StartNew(async () =>
        {
            using (var adapter = new DataAdapter())
            {
                // Take your time and fetch the data
            }
        });
        task.Wait();
        return true;
    }
}

感谢您对此的评论。

除了同步之外,没有其他方法可以运行同步方法。

您可以将结果包装在看起来像是异步运行的内容中(例如Task.FromResult ),或在另一个线程中运行。 1但是,同步方法仍然会阻塞正在运行的线程。

(相反,阻塞异步操作是微不足道的。这就是为什么您需要使基础操作异步的原因,因为您可以在顶部同时构建同步和异步方法。)

更新 (有问题的更新):

该附加代码(特别是task.Wait()语句)将导致调用方的线程在等待任务完成时阻塞。 该任务将在另一个线程上运行,导致该线程阻塞。 IE浏览器。 您正在导致两个线程(调用者和线程池线程)阻塞。 如果直接调用基础方法,则仅调用者的线程将被阻止。

您有两种方法:

  1. 最好:使用ADO.NET的异步操作。 (这意味着不使用DataTables / DataAdaptor但是恕我直言,这是一个好举动:他们所做的只是将应该在数据库上完成的操作移动到客户端中。)

  2. 卸载到另一个线程,但将Task<TResult>返回给调用者,仅将Task标记为完成,然后基础操作完成。 就像是:

     protected override Task<bool> GetData(params object[] getDataParams) { var tcs = new TaskCompletionSource<bool>(); Task.Factory.StartNew(async () => { using (var adapter = new DataAdapter()) { // Take your time and fetch the data tcs.SetResult(the-result); } }); return tcs.Task; } 

    请注意,这里从GetData返回的是Task<bool> :调用方需要等待或并发执行其他操作,然后获取数据操作的结果。 如果调用方只是等待,则您有两个阻塞的线程。 (C#5的await有所不同:调用方也将变为异步。)


1为避免疑问:可以使它看起来像是普通的Task<T>返回的异步方法(例如,使用TaskCompletionSource<T>来将当前线程的阻塞加载到线程池中的某个线程中) )。 但这仍然是一个阻塞操作:只是阻塞另一个线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM