Task.Run (asnyc () =>) Блокировка / не выполнение всех задач C # - PullRequest
0 голосов
/ 12 октября 2018

Проблема в том, что я пытаюсь запустить RunPrivateMethod () несколько раз, но у меня возникают проблемы с блокировкой или просто не работает, когда я использую async / await.Вместо того, чтобы делиться каждой попыткой здесь, я просто выкладываю свою текущую версию.

В RunPrivateMethod () метод exeProcess.WaitForExit () является внешней программой, которая в основном считывает / записывает / обрабатывает / выводит данные.Я попытался запустить это как асинхронную задачу, и это не сработало.

Я не знаю, является ли это рациональной задачей, но я хочу ограничить количество задач, которые запускаются одновременно, поэтому я ставлю Task.WaitAll () в конце каждого блока case.Case (1) и Case (2) всегда запускаются.

Итак, вот мой код.В настоящее время он блокируется при загрузке каждой задачи.Тогда кажется, что выполняется только последнее задание.Это работает правильно, если я вычеркну все операторы Task и выполню все нормально.

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

public void RunSomeTasks(int group)
    {

        switch (group)
        {

            case (1):
                {
                    Task.Run(async () => await RunAsyncMethod(param1, param1, group));
                    Task.Run(async () => await RunAsyncMethod(param1, param2, group));
                    Task.Run(async () => await RunAsyncMethod(param1, param3, group));
                    Task.WaitAll();
                    break;
                }
            case (2):
                {
                    Task.Run(async () => await RunAsyncMethod(param2, param1, group));
                    Task.Run(async () => await RunAsyncMethod(param2, param2, group));
                    Task.Run(async () => await RunAsyncMethod(param2, param3, group));
                    Task.WaitAll();
                    break;
                }
        }
    }

    async Task RunAsyncMethod(string var1, string var2, string varGroup)
    {           

        ////////////////////////////////////////////
        // Use ProcessStartInfo class
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.CreateNoWindow = false;
        startInfo.UseShellExecute = false;
        startInfo.FileName = "SomeOutsideEXE";
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        startInfo.Arguments = var1 + " " + var2 + " " + varGroup;
        using (Process exeProcess = Process.Start(startInfo))
        {
            // did not work -> Task.Run(() => exeProcess.WaitForExit()).Wait();
            exeProcess.WaitForExit();
        }
    }
}

Я работал над этим бесчисленное количество часов и читал книгу Клири, и эта последняя редакция является версией этого поста: Aync / Awaitдействие в Task.Run () Текущие результаты состоят в том, что последнее задание в каждом наборе работает, хотя exeProcess запускается в нужное время.Я не могу использовать клавиатуру во время ее работы.

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

Ответы [ 2 ]

0 голосов
/ 05 апреля 2019

Самый чистый способ, которым я придумал сделать await Process.WaitForExit, похож на это, сохраняет подписку на events и т. Д.

private async Task RunRubyScript(string filePath)
{
  await Task.Run(() =>
  {
    using (var proc = new Process())
    {
      var startInfo = new ProcessStartInfo(@"ruby");
      startInfo.Arguments = filePath;
      startInfo.UseShellExecute = false;
      startInfo.CreateNoWindow = true;
      proc.StartInfo = startInfo;
      proc.Start();
      proc.WaitForExit();
    }
  });
}

Это было для запуска скрипта rubyОднако, очевидно, измените вас ProcessStartInfo в соответствии с вашими требованиями.

Надеюсь, это поможет!

0 голосов
/ 12 октября 2018

Я немного изменил ваш пример, это должно удерживать интерфейс от блокировки.Обратите внимание, я добавил async к нажатию кнопки.Также используя WhenAll и передавая запущенные задачи, вместо использования WaitAll.(Обновлено для полного асинхронного режима)

    private async void button1_Click(object sender, EventArgs e)
    {
        try
        {
            await RunSomeTasks(1);
            await RunSomeTasks(2);
            lblStatus.Text = "done!";
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

    public async Task RunSomeTasks(int group)
    {
        switch (group)
        {
            case (1):
                {
                    var t1 = RunMethodAsync(param1, param1, group);
                    var t2 = RunMethodAsync(param1, param2, group);
                    var t3 = RunMethodAsync(param1, param3, group);
                    await Task.WhenAll(t1, t2, t3).ConfigureAwait(false);
                    break;
                }
            case (2):
                {
                    var t1 = RunMethodAsync(param2, param1, group);
                    var t2 = RunMethodAsync(param2, param2, group);
                    var t3 = RunMethodAsync(param2, param3, group);
                    await Task.WhenAll(t1, t2, t3).ConfigureAwait(false);
                    break;
                }
        }
    }

    async Task RunMethodAsync(string var1, string var2, int varGroup)
    {
        ////////////////////////////////////////////
        // Use ProcessStartInfo class
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.CreateNoWindow = false;
        startInfo.UseShellExecute = false;
        startInfo.FileName = "SomeOutsideEXE";
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        startInfo.Arguments = var1 + " " + var2 + " " + varGroup;

        using (Process exeProcess = new Process())
        {
            var cts = new TaskCompletionSource<int>();

            exeProcess.StartInfo = startInfo;
            exeProcess.EnableRaisingEvents = true;

            exeProcess.Exited += (sender, e) =>
            {
                try
                {
                    cts.SetResult(exeProcess.ExitCode);
                }
                catch (Exception ex)
                {
                    cts.SetException(ex);
                }
            };

            exeProcess.Start();

            await cts.Task.ConfigureAwait(false);
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...