C # пропускает DispatcherOperation - PullRequest
       8

C # пропускает DispatcherOperation

0 голосов
/ 20 февраля 2019

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

CancellationTokenSource _cts;

async void asyncMethod()
{
    // ..................   

    _cts = new CancellationTokenSource();
            var progress = new Progress<double>(value => pbCalculationProgress.Value = value);
            try
            {
                _cts.CancelAfter(25000);
                int count = await awaitMethod(_cts.Token, progress);
            }
            catch (OperationCanceledException ex)
            {
        // .......
            }
            finally
            {
                _cts.Dispose();
            }

    // ..................
}

async Task<int> awaitMethod(CancellationToken ct, IProgress<double> progress)
{
            var task = Task.Run(() =>
            {
                ct.ThrowIfCancellationRequested();
                sqlParser();                
                progress.Report(1);
                return 0;
            });
            return await task;
}

void sqlParser()
{
    string info = form1TxtBox.Text;

    // ................
}

Кроме того, программа выдает исключение, потому что sqlParser () обновляет поток пользовательского интерфейса, когда он получает текст из формы.Решением является введение метода Dispatcher, который позволяет обновлять пользовательский интерфейс.Я сохраняю тело awaitMethod таким же и просто помещаю sqlParser () внутри Dispatcher:

DispatcherOperation op = Dispatcher.BeginInvoke((Action)(() =>
                {
                    sqlParser();
                })); 

Здесь происходит нечто интересное: asyncMethod () даже не смеет вызывать awaitMethod!Однако, если я помещаю точку останова в sqlParser () и запускаю отладчик, то все идет очень гладко.

Пожалуйста, кто-нибудь может объяснить, что мне не хватает в моем коде?Какой патч я должен использовать для корректной работы Dispatcher?Или: как я могу запустить свою программу без Dispatcher и без исключения UI-update?

1 Ответ

0 голосов
/ 20 февраля 2019

Решением является введение метода Dispatcher, который позволяет обновлять пользовательский интерфейс.

Это никогда не является хорошим решением.Наличие фоновых потоков, попадающих непосредственно в ваш пользовательский интерфейс, поощряет спагетти-код.

как я могу запустить мою программу без Dispatcher и без исключения UI-update?

Подумайте о своемФоновый код потока как отдельный компонент, полностью отделенный от пользовательского интерфейса.Если вашему фоновому коду требуются данные из пользовательского интерфейса, то перед тем, как начнется фоновый код, прочитайте его в коде пользовательского интерфейса и передайте эти данные в фоновый код.

async void asyncMethod()
{
  ...
  try
  {
    var data = myUiComponent.Text;
    _cts.CancelAfter(25000);
    int count = await awaitMethod(data, _cts.Token, progress);
  }
  ...
}

async Task<int> awaitMethod(string data, CancellationToken ct, IProgress<double> progress)
{
  var task = Task.Run(() =>
  {
    ct.ThrowIfCancellationRequested();
    sqlParser(data);
    progress.Report(1);
    return 0;
  });
  return await task;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...