Как заставить асинхронный метод возвращать значение? - PullRequest
67 голосов
/ 18 мая 2011

Я знаю, как создавать асинхронные методы, но говорю, что у меня есть метод, который выполняет большую часть работы и возвращает логическое значение?

Как вернуть логическое значение при обратном вызове?

Разъяснение

public bool Foo(){
    Thread.Sleep(100000); // Do work
    return true;
}

Я хочу сделать это асинхронным.

Ответы [ 6 ]

115 голосов
/ 18 мая 2011

С C # 5.0 , вы можете указать метод как

public async Task<bool> doAsyncOperation()
{
    // do work
    return true;
}

bool result = await doAsyncOperation();
53 голосов
/ 18 мая 2011

Есть несколько способов сделать это ... самый простой - это заставить асинхронный метод также выполнить последующую операцию.Другой популярный подход заключается в передаче обратного вызова, т. Е.

void RunFooAsync(..., Action<bool> callback) {
     // do some stuff
     bool result = ...

     if(callback != null) callback(result);
}

Другой подход заключается в создании события (с результатом в данных аргументов события), когда асинхронная операция завершена.

Кроме того, если вы используете TPL, вы можете использовать ContinueWith:

Task<bool> outerTask = ...;
outerTask.ContinueWith(task =>
{
    bool result = task.Result;
    // do something with that
});
4 голосов
/ 18 мая 2011

Вероятно, самый простой способ сделать это - создать делегата, а затем 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);
}
3 голосов
/ 18 мая 2011

Используйте BackgroundWorker. Это позволит вам получить обратные вызовы по завершении и позволит вам отслеживать прогресс. Вы можете установить значение Result для аргументов события равным полученному значению.

    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;
    }
1 голос
/ 29 октября 2013

Возможно, вы можете попробовать 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, чтобы продолжить ..

0 голосов
/ 18 мая 2011

Вы должны использовать EndXXX вашего асинхронного метода для возврата значения. EndXXX должен подождать, пока не будет получен результат, используя WaitHandle объекта IAsyncResult и затем вернуться со значением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...