IAsyncresult - опрос без зависания интерфейса? - PullRequest
0 голосов
/ 12 мая 2011

У меня Windows svc, который работает асинхронно (я отредактировал методы и их параметры, чтобы сделать их асинхронными), немного похоже на: http://msdn.microsoft.com/en-us/library/ms731177.aspx

Однако я вызываю задачу, которую хочу запустить асинхронно (вызов службы / сервера), а затем обновляю пользовательский интерфейс (используя ReportProgress () на backgroundworker - все это происходит в методе dowork () фонового работника). Однако я вызываю метод Endxxx для получения результатов, но проблема в том, должен ли мой код выглядеть?

while (!asyncresult.IsCompleted) { // Do all UI updating etc here... }

// Call endXXX here.

Однако этот подход блокирует пользовательский интерфейс. На данный момент мой код выглядит примерно так (и не блокирует интерфейс):

 IAsyncResult res = null;

                try
                {

                    res = serviceX.BeginXXX(ResultCallBack, "");
                }
                catch (FaultException<ManagementException> managementEx)
                {
                    Logger.Error(managementEx.Detail.ToString());
                    MessageBox.Show("Could not add printer. See log.");
                }



                    InstallBackgoundWorker.ReportProgress(90);
                    InstallBackgoundWorker.ReportProgress(91);
                    InstallBackgoundWorker.ReportProgress(93);

                    InstallBackgoundWorker.ReportProgress(94);
                    InstallBackgoundWorker.ReportProgress(95);
                    InstallBackgoundWorker.ReportProgress(96);
                    InstallBackgoundWorker.ReportProgress(97);



                    if (res.IsCompleted)
                    {
                        ResultCallBack(res);
                    }
                    InstallBackgoundWorker.ReportProgress(100);

Это правильно? Мне кажется, это неправильно.

Ответы [ 2 ]

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

Я не уверен, что вы используете шаблон асинхронности правильно. Это должно выглядеть примерно так:

void Start()
{
    System.IO.Stream s = ...;
    byte[] buf = ...;

    // start the IO.

    s.BeginRead(buf, 0, buf.Length, res =>
        {
            // this gets called when it's finished,
            // but you're in a different thread.

            int len = s.EndRead(res);

            // so you must call Dispatcher.Invoke
            // to get back to the UI thread.

            Dispatcher.Invoke((Action)delegate
                {
                    // perform UI updates here.
                });
        }, null);

    // the IO is started (and maybe finished) here,
    // but you probably don't need to put anything here.
}

Написано с Stream, потому что я не знаю сигнатуру вашего объекта, но, надеюсь, вы поняли идею! Вам нужно обработать завершение операции в обратном вызове, который вы ей дали, , а не непосредственно после вызова метода Begin. Вам не нужно опрашивать свойство IsCompleted.

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

Нет, вы не должны использовать первый подход, поскольку он не соответствует цели вызова метода асинхронным способом.

Второй подход также проблематичен, поскольку

  • ваши отчеты о прогрессепроизвольно и нереально
  • даже при 100% это не гарантирует, что работа выполнена, поскольку при 100% она не знает, была ли работа выполнена.

Нетспособ показать отчет о ходе выполнения асинхронного задания, если только асинхронное не предоставляет его.

Решение:

  • Отображение неопределенного индикатора выполнения (также называемого счетчиком)
  • Отчет пользователя о результате внутриобратный вызов

Вы также должны знать о проблемах связи с потоком пользовательского интерфейса из фонового потока и использования Invoke в Windows Forms и использования Dispatcher в WPF.

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