【发布时间】:2017-01-25 00:32:51
【问题描述】:
我有一个抽象类,它的方法是这样定义的
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;
}
}
感谢您的 cmets。
【问题讨论】:
-
您的使用不是异步的——您是在后台线程中启动任务,但主线程只是坐在那里等待它。直接返回任务或
await任务或类似。根据定义,抽象类中的方法是同步的,所以除非你能改变你的运气。 -
查看TaskCompletionSource
-
请发布您的实际数据访问代码,而不是包装器。 ADO.NET 具有异步方法,例如
ExecuteReaderAsync和ExecuteNonQueryAsync。像 EF 这样的 ORM 和像 Dapper 这样的 microORM 也提供异步方法。很可能您的实际数据访问代码可以修改为异步运行。 -
回复:您的更新 - 您的主线程仍在阻塞此方法,并且它总是直到您的方法签名更改。你能解释一下你想在这里实现什么吗?您只是想避免阻塞 UI 线程,还是实际上期望操作系统级别的异步?
-
好的,Richard 的回答指出你不能通过包装方法来实现操作系统级别的异步——这不会改变幕后发生的事情。您需要为此使用异步 API。关于不阻塞 UI 线程,为了实现这一点,您需要更改
GetData的方法签名,因此它也返回一个任务(通过直接返回包装的任务或使用 async/await) - 你需要一直到你的 UI 执行此操作,否则 UI 线程仍将被阻塞在某个地方。
标签: c# asynchronous task-parallel-library .net-4.5