Как заставить асинхронный метод вернуть значение?
Я знаю, как сделать методы Async, но сказать, что у меня есть метод, который выполняет много работы, а затем возвращает логическое значение?
Как вернуть логическое значение в обратном вызове?
Разъяснение
public bool Foo(){
Thread.Sleep(100000); // Do work
return true;
}
Я хочу иметь возможность сделать это асинхронным.
Ответы
Ответ 1
Есть несколько способов сделать это... самым простым является использование метода async и последующего действия. Другой популярный подход - передать обратный вызов, т.е.
void RunFooAsync(..., Action<bool> callback) {
// do some stuff
bool result = ...
if(callback != null) callback(result);
}
Другим подходом было бы поднять событие (с результатом в данных event-args), когда операция async будет завершена.
Кроме того, если вы используете TPL, вы можете использовать ContinueWith
:
Task<bool> outerTask = ...;
outerTask.ContinueWith(task =>
{
bool result = task.Result;
// do something with that
});
Ответ 2
Из С# 5.0 вы можете указать метод как
public async Task<bool> doAsyncOperation()
{
// do work
return true;
}
bool result = await doAsyncOperation();
Ответ 3
Вероятно, самый простой способ сделать это - создать делегат, а затем BeginInvoke
, а затем ждать некоторое время в будущем и EndInvoke
.
public bool Foo(){
Thread.Sleep(100000); // Do work
return true;
}
public SomeMethod()
{
var fooCaller = new Func<bool>(Foo);
// Call the method asynchronously
var asyncResult = fooCaller.BeginInvoke(null, null);
// Potentially do other work while the asynchronous method is executing.
// Finally, wait for result
asyncResult.AsyncWaitHandle.WaitOne();
bool fooResult = fooCaller.EndInvoke(asyncResult);
Console.WriteLine("Foo returned {0}", fooResult);
}
Ответ 4
Используйте BackgroundWorker. Это позволит вам получить обратные вызовы по завершении и позволит вам отслеживать прогресс. Вы можете установить значение результата для аргументов события в результирующее значение.
public void UseBackgroundWorker()
{
var worker = new BackgroundWorker();
worker.DoWork += DoWork;
worker.RunWorkerCompleted += WorkDone;
worker.RunWorkerAsync("input");
}
public void DoWork(object sender, DoWorkEventArgs e)
{
e.Result = e.Argument.Equals("input");
Thread.Sleep(1000);
}
public void WorkDone(object sender, RunWorkerCompletedEventArgs e)
{
var result = (bool) e.Result;
}
Ответ 5
Возможно, вы можете попробовать BeginInvoke делегата, указывающего на ваш метод следующим образом:
delegate string SynchOperation(string value);
class Program
{
static void Main(string[] args)
{
BeginTheSynchronousOperation(CallbackOperation, "my value");
Console.ReadLine();
}
static void BeginTheSynchronousOperation(AsyncCallback callback, string value)
{
SynchOperation op = new SynchOperation(SynchronousOperation);
op.BeginInvoke(value, callback, op);
}
static string SynchronousOperation(string value)
{
Thread.Sleep(10000);
return value;
}
static void CallbackOperation(IAsyncResult result)
{
// get your delegate
var ar = result.AsyncState as SynchOperation;
// end invoke and get value
var returned = ar.EndInvoke(result);
Console.WriteLine(returned);
}
}
Затем используйте значение в методе, отправленном как AsyncCallback, чтобы продолжить.
Ответ 6
Вы должны использовать EndXXX вашего метода async, чтобы вернуть значение. EndXXX должен ждать, пока результат не будет получен с помощью IAsyncResult WaitHandle, а затем вернется со значением.