Я хотел бы знать, как написать свои собственные асинхронные методы "правильным" способом.
Я видел много сообщений, объясняющих шаблон async/await следующим образом:
http://msdn.microsoft.com/en-us/library/hh191443.aspx
// Three things to note in the signature:
// - The method has an async modifier.
// - The return type is Task or Task<T>. (See "Return Types" section.)
// Here, it is Task<int> because the return statement returns an integer.
// - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
private void DoIndependentWork()
{
resultsTextBox.Text += "Working........\r\n";
}
Это отлично работает для любого .NET-метода, который уже реализует эту функциональность, например
- Операции System.IO
- Операции с DataBase
- Операции, связанные с сетью (загрузка, загрузка...)
Но что, если я хочу написать свой собственный метод, который занимает довольно много времени, чтобы завершить то, где просто нет метода, который я могу использовать, и большая нагрузка находится в методе DoIndependentWork
в приведенном выше примере?
В этом методе я мог бы сделать:
- Обработка строк
- Вычисления
- Обработка моих собственных объектов
- Агрегирование, сравнение, фильтрация, группировка, обработка материалов.
- Список операций, добавление, удаление, копирование
Снова я наткнулся на многие сообщения, где люди просто делают следующее (снова беря приведенный выше пример):
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
await DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
private Task DoIndependentWork()
{
return Task.Run(() => {
//String manipulations
//Calculations
//Handling my own objects
//Aggregating, comparing, filtering, grouping, handling stuff
//List operations, adding, removing, coping
});
}
Вы можете заметить, что изменения состоят в том, что DoIndependentWork
теперь возвращает задачу и в задаче AccessTheWebAsync
метод получил await
.
Операции с большой нагрузкой теперь закрываются внутри Task.Run()
, это все, что требуется?
Если это все, что требуется, это единственное, что мне нужно сделать, чтобы предоставить async Method для каждого отдельного метода в моей библиотеке следующее:
public class FooMagic
{
public void DoSomeMagic()
{
//Do some synchron magic...
}
public Task DoSomeMagicAsync()
{
//Do some async magic... ?!?
return Task.Run(() => { DoSomeMagic(); });
}
}
Было бы неплохо, если бы вы могли объяснить это мне, так как даже высокий голосовой вопрос вроде этого: Как написать простой метод async? объясняет это только с уже существующими методами и просто использует шаблон asyn/await, как этот комментарий по указанному вопросу приводит его к сути: Как написать простой метод асинхронизации?