#c# #asynchronous #task #background-service
#c# #асинхронный #задача #фоновая служба
Вопрос:
Оправдано ли использование Task.Run
в этом случае?
В настоящее время я запускаю этот код в приложении WinForms, но позже он будет использоваться в ASP.NET проект как HostedService
/ BackgroundService
. Я не уверен, сравнимо ли это тогда.
После прочтения нескольких блогов об async / await и Tasks
я чувствую Task.Run(() => ..
, что это должно быть реализовано в вызывающем методе 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);
}
}
}
Ответ №1:
Во-первых, вы можете изменить IConnection
? Является ли эта синхронная реализация основной или это всего лишь одна из многих?
Если вы можете изменить IConnection
, то сделайте это синхронным, и вы можете использовать Task.Run
в реализации ExecuteAsync
.
Если IConnection
необходимо оставаться асинхронным, я бы сказал, реализовать ConnectionA.ReadAsync
синхронно. Затем введите Task.Run
ExecuteAsync
как обычно. Ключом к этому методу является то, что асинхронная ( Task
возвращающая) подпись означает, что реализация может быть асинхронной, а не то, что она должна быть асинхронной.
Комментарии:
1. Я контролирую интерфейс IConnection. Но конкретная реализация может быть синхронизирована или асинхронна. Тем не менее, я всегда хочу быть уверенным, что без необходимости не блокирую какой-либо поток. Я думаю, я соглашусь с вашим предложением реализовать Task.Run в методе ExecuteAsync, так как я все равно должен это сделать (см. Вашу ошибку BackgroundService ;))
2. ОК. Тогда я бы оставил
IConnection.ReadAsync
подпись асинхронной и просто разрешил как асинхронные, так и синхронные реализации.3. Под «сохраняйте последовательность как однонаправленную» вы имеете в виду, что я должен сохранить асинхронное именование и обеспечить асинхронное выполнение при
Task.Run
вызовеExecuteAsync
? Просто для моего пояснения.4. Да; под «асинхронной сигнатурой» я подразумеваю
Async
суффикс иTask
(или подобный задаче) возвращаемый тип.