0

在我的 Winforms 应用程序中,当您启动操作时,它可能会或可能不会异步完成。在工作全部同步完成的情况下,我无法使用异步完成工作时使用的相同方法显示等待光标。

这是一个显示该问题的示例:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var t = ButtonClick(button1, DoWorkAsync1);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        var t = ButtonClick(button2, DoWorkAsync2);
    }

    private async Task ButtonClick(Button btn, Func<Task> doWorkAsync)
    {
        // Disable the UI and show the wait cursor
        btn.Text = "Working...";
        btn.Enabled = false;
        UseWaitCursor = true;

        // Application.DoEvents(); // Inserting this causes the problem to go away.
        await doWorkAsync();

        // Simulate an update of the UI taking a long time
        Thread.Sleep(2000); 

        // Renable the UI and stop showing the wait cursor
        UseWaitCursor = false;
        btn.Enabled = true;
    }

    private Task DoWorkAsync1()
    {
        // Work takes some time
        return Task.Delay(2000); 
    }

    private Task DoWorkAsync2()
    {
        // Work doesn't take any time, results are immediately available
        return Task.FromResult<int>(0); 
    }
}

在这个例子中:

  • 单击 button1 会显示等待光标(因为工作是异步完成的)。
  • 单击 button2 不会显示Wait 光标(因为所有工作都是同步完成的)。
  • 单击 button1 和 button2 会导致 UI 按预期被禁用。

需要的是,单击按钮 1 或按钮 2 应导致在单击按钮和 UI 更新工作完成之间的整个间隔内显示等待光标。

问题:

  • 有没有办法在不插入Application.DoEvent(也没有任何会导致消息泵送发生的等效物)的情况下解决这个问题,或者只有通过泵送消息才有可能。
  • 顺便说一句:为什么禁用控件可以正常工作(与光标不同)。
4

2 回答 2

0

而不是DoEvents投入:

await Task.Run(() => { });

这将确保等待的任务在启动时不会正确完成,因此该方法的其余部分将作为继续运行,而不是同步运行。

或者,您可以直接添加一个延续,以doWorkAsync确保不会同步运行:

await doWorkAsync
    .ContinueWith(t => { }, TaskContinuationOptions.HideScheduler);
于 2013-08-20T18:36:34.790 回答
0

如果您有要在后台线程上执行的同步工作,请在 a 中调用它,Task.Run然后await调用结果(调用代码将其视为异步)。

private Task DoWorkAsync1()
{
    return Task.Delay(2000); 
}

private Task DoWorkAsync2()
{
    return Task.Run(() => Thread.Sleep(2000));
}

或者,如果您的同步工作确实是即时的,并且您确实想在其他 UI 工作之前应用一些 UI 更新(例如,光标),那么您可以简单地执行以下操作:

await Task.Delay(10);
于 2013-08-20T18:27:52.410 回答