C# 所有工作同步时显示等待光标
在我的Winforms应用程序中,启动操作时,可以异步执行,也可以不异步执行。在所有工作都是同步完成的情况下,我无法使用异步完成工作时使用的相同方法显示等待光标 下面是一个显示问题的示例:C# 所有工作同步时显示等待光标,c#,winforms,async-await,C#,Winforms,Async Await,在我的Winforms应用程序中,启动操作时,可以异步执行,也可以不异步执行。在所有工作都是同步完成的情况下,我无法使用异步完成工作时使用的相同方法显示等待光标 下面是一个显示问题的示例: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs
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);
}
}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
变量t=按钮单击(按钮1,DOWORKSync1);
}
私有无效按钮2\u单击(对象发送者,事件参数e)
{
变量t=按钮单击(按钮2,DOWORKSync2);
}
专用异步任务按钮单击(按钮btn,Func doWorkAsync)
{
//禁用UI并显示等待光标
btn.Text=“工作…”;
btn.Enabled=false;
UseWaitCursor=true;
//Application.DoEvents();//插入此选项会导致问题消失。
等待doWorkAsync();
//模拟花很长时间更新UI
《睡眠》(2000年);
//重新启动UI并停止显示等待光标
UseWaitCursor=false;
btn.Enabled=true;
}
专用任务DoWorkAsync1()
{
//工作需要一些时间
返回任务。延迟(2000);
}
专用任务DoWorkAsync2()
{
//工作不需要任何时间,结果立即可用
返回Task.FromResult(0);
}
}
在本例中:
- 单击按钮1会显示等待光标(因为工作是异步完成的)
- 单击按钮2不会显示等待光标(因为所有工作都是同步完成的)
- 单击按钮1和按钮2都会按预期禁用UI
- 有没有办法解决这个问题而不插入
(或任何会导致消息泵送发生的等效程序),或者只能通过泵送消息来实现应用程序.DoEvent
- 旁白:为什么控件的禁用工作正常(与光标不同)
任务中调用它。运行然后等待结果(调用代码将其视为异步)
或者,如果您的同步工作确实是即时的,并且您确实希望在其他UI工作之前应用一些UI更新(例如,游标),那么您只需执行以下操作:
await Task.Delay(10);
而不是DoEvents
插入:
await Task.Run(() => { });
这将确保等待的任务在启动时没有正确完成,因此该方法的其余部分将作为延续而不是同步运行
或者,您可以直接向doworksync
添加一个continuation,以确保它不会同步运行:
await doWorkAsync
.ContinueWith(t => { }, TaskContinuationOptions.HideScheduler);
我没有我想在后台线程上做的同步工作。如果你真的有2秒的UI工作要做,那么这就是所需要的时间。没有魔法。我不想要任何魔法——我想在这两秒钟内显示等待光标。关键是2秒钟的UI更新表明存在严重的设计问题。也许您应该使用虚拟化控件?等待光标不用于显示UI更新;也就是说,我已经用一个黑客更新了我的答案,应该可以做你想要的。可能是@HansPassant的重复,谢谢——答案是:UseWaitCursor正在等待WM_SETCURSOR消息。此解决方案适合我。@MattSmith SetCursor将帮助您显示任何类型的自定义游标或标准游标,等待游标
只是一件非常简单的事情。为什么不等待任务。Yield()
?@svick我运行了一些测试,但它不起作用。这是我第一次想到什么应该有效。嗯,空线程池任务可以很容易地以非确定性的方式内联。为什么屈服不起作用?好奇。@usr AFAIKwait
从不内联Task
s。当然不是UI线程。虽然任务
在等待
ed之前完成的可能性很小。
await doWorkAsync
.ContinueWith(t => { }, TaskContinuationOptions.HideScheduler);