Вызов синхронных методов асинхронно в потоке пользовательского интерфейса - PullRequest
1 голос
/ 10 марта 2009

Я написал класс, который проверяет учетную запись POP3, и я хотел бы, чтобы он выполнялся в потоке, отличном от потока пользовательского интерфейса.

Для этого я выбрал асинхронный маршрут.

Чтобы получить результат от pop3delegate.BeginInvoke (null, null), мне нужно вызвать EndInvoke, но сделать это в блоках потока пользовательского интерфейса, делая пользовательский интерфейс непригодным для использования.

Я мог бы использовать объект IAsyncResult и проверить свойство IsComplete, но это включает в себя цикл, который проверяет, и это в свою очередь блокирует пользовательский интерфейс.

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

Есть предложения?

Ответы [ 5 ]

3 голосов
/ 10 марта 2009

Попробуйте использовать класс BackgroundWorker, он был разработан, чтобы делать именно то, что вам нужно.

Пример и более подробная информация о msdn: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

0 голосов
/ 10 марта 2009

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

private delegate int LongRunningTaskHandler();
static void Main(string[] args) {
    LongRunningTaskHandler handler = LongRunningTask;
    handler.BeginInvoke(MyCallBack, null);
    Console.ReadLine();
}
private static void MyCallBack(IAsyncResult ar) {
    var result = (LongRunningTaskHandler)((AsyncResult) ar).AsyncDelegate;
    Console.WriteLine(result.EndInvoke(ar));
}
public static int LongRunningTask()
{
    Thread.Sleep(5000);
    return 42;
}
0 голосов
/ 10 марта 2009

Использовать событие и пул потоков

var asyncResult = pop3delegate.BeginInvoke(null,null);
ThreadPool.RegisterWaitForSingleObject(
    asyncResult.WaitHandle, FunctionToCallWhenDone, null, TimeSpan.Infinite, true);

Это вызовет ваш FunctionToCallWhenDone при поступлении данных. Вы также используете ThreadPool, который должен быть дешевле, чем создание собственного потока. Однако, как заметил Курт Шелфтоут, вам нужно будет сделать что-то вроде uielement.Invoke (() => {некоторый код}), чтобы изменить интерфейс.

0 голосов
/ 10 марта 2009

Используйте BackgroundWorker. Это также избавляет вас от необходимости перенаправлять данные назад и вперед между пользовательским интерфейсом и фоновыми потоками, а также позволяет получать уведомления о прогрессе и отмену.

0 голосов
/ 10 марта 2009

Попробуйте Фоновщик класс.

...