如果使用Task.Run
在这种情况下,是否合理呢?
当前,我在WinForms应用程序中运行此代码,但稍后将在ASP.NET项目中将其用作HostedService
/ BackgroundService
。我不确定这是否具有可比性。
在阅读了有关async / await的多个博客之后,Tasks
我觉得Task.Run(() => ..
应该在calling方法中实现Manager.SyncLoop()
。但是,如果的实现IConnection
是真正异步的,那不是代码的味道吗?
private async void button1_Click(object sender, EventArgs e)
{
// this should be handled by the BackgroudService, WinForms is used just for testing
var m = new Manager();
m.Connection = new ConnectionA();
m.ExecuteAsync();
}
}
public interface IConnection
{
Task<object> ReadAsync();
}
// assume that i cannot change this
public class SomeLib
{
private Random random = new Random();
public object SyncReading()
{
Thread.Sleep(5000);
return random.Next(); ;
}
}
public class ConnectionA : IConnection
{
private SomeLib lib = new SomeLib();
public Task<object> ReadAsync()
{
// is this usage of Task.Run ok?
var v = Task.Run(() => lib.SyncReading());
return v;
}
// this will block UI
//public Task<object> ReadAsync()
//{
// return Task.FromResult(lib.SyncReading());
//}
}
public class Manager
{
public IConnection Connection { get; set; }
public async Task ExecuteAsync()
{
await SyncLoop();
}
public async Task SyncLoop()
{
while (true)
{
var i = await Connection.ReadAsync();
await Task.Delay(2000);
}
}
}
首先,你可以改变IConnection
吗?此同步实现是主要实现,还是仅仅是众多实现之一?
如果可以更改IConnection
,则使其同步,并可以在中使用Task.Run
ExecuteAsync
。
如果IConnection
需要保持异步,那么我会说要实现ConnectionA.ReadAsync
同步。然后像往常一样Task.Run
放入ExecuteAsync
。该技术背后的关键是异步(-Task
返回)签名意味着实现可以是异步的,而不是必须是异步的。
我可以控制IConnection接口。但是具体的实现可以是同步的也可以是异步的。不过,我始终希望确保不要不必要地阻塞某些线程。我想我会根据您的建议在ExecuteAsync方法中实现Task.Run,因为无论如何我都必须这样做(请参阅您的BackgroundService Gotcha;))
好的。
IConnection.ReadAsync
然后,我将签名保持异步,并且只允许异步和同步实现。所谓“保持单数异步”,是指我应保持异步命名,并确保通过?中的
Task.Run
调用来异步执行ExecuteAsync
。仅出于我的澄清。是的; “异步签名”是指
Async
后缀和Task
(或类似任务的)返回类型。