Как сделать задержку между выполнением двух методов? - PullRequest
0 голосов
/ 22 марта 2020

Я использую async / await для задержки между выполнением метода.

Существует код

public bool DoPerformCommandOnClient(string commandStr, bool isOnPath, string folderPath, string ext, string doneMessage, string excludeString)
{
    Task.Run(() => DoOpenProgressBarWindowWithDelay(2000));
    return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);
}
public async void DoOpenProgressBarWindowWithDelay(int delay)
{
    BeginInvoke((Action)(() => {
        DoOpenProgressBarWindow();
    }));
    await Task.Delay(delay);
}

Итак, я хотел бы выполнить метод DoPerformCommandOnClient затем после 2 se c delay выполните следующую строку

return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);

Но вместо этого этот метод DoPerformCommandOnClient выполняется без задержки.

Затем я попытался добавить Thread.Sleep(2000) между двумя строками

public bool DoPerformCommandOnClient(string commandStr, bool isOnPath, string folderPath, string ext, string doneMessage, string excludeString)
{
    DoOpenProgressBarWindow();
    Thread.Sleep(2000);
    return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);
}

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

Итак, вопрос в том, как сделать задержку между двумя методами?

РЕДАКТИРОВАТЬ

теперь код выглядит следующим образом

public bool DoPerformCommandOnClient(string commandStr, bool isOnPath, string folderPath, string ext, string doneMessage, string excludeString)
{
    Task.Run(() => DoOpenProgressBarWindowWithDelay(2000)).Wait();
    return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);
}

public async void DoOpenProgressBarWindowWithDelay(int delay)
{
    BeginInvoke((Action)(() => {
        DoOpenProgressBarWindow();
    }));
    await Task.Delay(delay).ConfigureAwait(false);
}

EDIT2

Теперь код выглядит следующим образом

public async Task<bool> DoPerformCommandOnClient(string commandStr, bool isOnPath, string folderPath, string ext, string doneMessage, string excludeString)
        {
            await DoOpenProgressBarWindowWithDelay(2000).ConfigureAwait(false);
            return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);
        }

        public async Task<bool> DoOpenProgressBarWindowWithDelay(int delay)
        {
            BeginInvoke((Action)(() =>
            {
                DoOpenProgressBarWindow();
            }));

            await Task.Delay(delay).ConfigureAwait(false);

            return true;
        }

EDIT3

public async Task<bool> DoPerformCommandOnClient(string commandStr, bool isOnPath, string folderPath, string ext, string doneMessage, string excludeString)
        {
            await DoOpenProgressBarWindowWithDelay(2000).ConfigureAwait(false);
            return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);
        }

        public async Task DoOpenProgressBarWindowWithDelay(int delay)
        {
            BeginInvoke((Action)(() =>
            {
                DoOpenProgressBarWindow();
            }));

            await Task.Delay(delay).ConfigureAwait(false);
        }

Есть способ, которым я называю этот метод

if (!m_MyManagerMainForm.DoPerformCommandOnClient(cmd1, true, sourcePath, "bmp", "ColorImageDone", "_M"))
            {
                RestoreGUIFromCalibration();
                return;
            }

, но он не работает, он говорит, что я могу неявно конвертировать Task<bool> to bool

Ответы [ 2 ]

1 голос
/ 22 марта 2020

Task.Run ставит в очередь действие, выполняемое в пуле потоков, и немедленно возвращается.

В вашем случае нет необходимости звонить Task.Run. Сделайте DoPerformCommandOnClient asyn c и ожидайте DoOpenProgressBarWindowWithDelay:

public async Task<bool> DoPerformCommandOnClient(string commandStr, bool isOnPath, string folderPath, string ext, string doneMessage, string excludeString)
{
    await DoOpenProgressBarWindowWithDelay(2000);
    return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);
}

Не звоните Wait (редактировать: это было предложено другим ответом), следующее заблокирует ваш поток (так же, как вызов Thread.Sleep(2000)):

public bool DoPerformCommandOnClient(string commandStr, bool isOnPath, string folderPath, string ext, string doneMessage, string excludeString)
{
    DoOpenProgressBarWindowWithDelay(2000).Wait();
    return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);
}

В качестве отступления, если ваш код не работает в «контексте приложения» (winforms или wpf) вызов ConfigureAwait(false), когда вы ожидаете или вы рискуете тупиковыми ситуациями. Кроме того, избегайте async void для методов, которые не являются обработчиками событий :

public async Task DoOpenProgressBarWindowWithDelay(int delay)
{
    BeginInvoke((Action)(() => {
        DoOpenProgressBarWindow();
    }));

    await Task.Delay(delay).ConfigureAwait(false);
}
1 голос
/ 22 марта 2020

ОБНОВЛЕНИЕ

Плохо, я не видел, чтобы ожидание происходило в потоке пользовательского интерфейса . Теперь я обновил свой ответ здесь и назову это невозможным, если метод syn c и пользовательский интерфейс не должен зависать.

Существует только один поток пользовательского интерфейса. И если он заблокирован по методу syn c. Пользовательский интерфейс точно зависает.

Я рекомендую сделать DoPerformCommandOnClient asyn c, чтобы задача могла быть должным образом ожидаема, а поток пользовательского интерфейса мог быть возвращен во время ожидания:

public async Task<bool> DoPerformCommandOnClient(string commandStr, bool isOnPath, string folderPath, string ext, string doneMessage, string excludeString)
{
    await Task.Run(() => DoOpenProgressBarWindowWithDelay(2000));
    return GetLogic().PerformCommandOnClient(commandStr, isOnPath, folderPath, ext, doneMessage, excludeString);
}

Если метод должен быть syn c, то я рекомендую поставить в очередь работу на ThreadPool, в рабочем потоке подождать 2 секунды и перенаправить продолжение обратно в поток пользовательского интерфейса.

...