Как заставить асинхронный метод возвращать значение?
Я знаю, как сделать асинхронные методы, но сказать, что у меня есть метод, который делает много работы, а затем возвращает логическое значение?
Как вернуть логическое значение при обратном вызове?
уточнение:
public bool Foo(){
Thread.Sleep(100000); // Do work
return true;
}
Я хочу быть в состоянии сделать это асинхронно.
6 ответов:
есть несколько способов сделать это... самое простое-иметь асинхронный метод и выполнять последующую операцию. Другим популярным подходом является передача обратного вызова, т. е.
void RunFooAsync(..., Action<bool> callback) { // do some stuff bool result = ... if(callback != null) callback(result); }
другой подход заключается в том, чтобы вызвать событие (с результатом в данных event-args), когда асинхронная операция завершена.
кроме того, если вы используете TPL, вы можете использовать
ContinueWith
:Task<bool> outerTask = ...; outerTask.ContinueWith(task => { bool result = task.Result; // do something with that });
С C# 5.0, вы можете указать способ, как
public async Task<bool> doAsyncOperation() { // do work return true; } bool result = await doAsyncOperation();
вероятно, самый простой способ сделать это-создать делегат, а затем
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); }
используйте 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; }
возможно, вы можете попробовать начать вызывать делегат, указывающий на ваш метод следующим образом:
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, чтобы продолжить..