Akh*_*hil 5 c# multithreading winforms
可能重复:
如何在后台线程运行时阻止Winforms UI
我正在使用C#WinForm应用程序
我在屏幕上有一个Save按钮,屏幕数据保存到数据库中.
当用户点击按钮应用程序进入数据库并保存数据时会发生什么.这需要一些时间.
但是,如果用户再次单击"保存"按钮,则会触发Click事件,当第一次单击返回主代码(保存数据库后)时,捕获的事件将被触发.
简而言之,当线程从第一个事件返回时,会捕获并触发click事件(我尝试了启用/禁用按钮的方案).
我怎样才能阻止这种行为.
此致,Akhil
@Jalal:我尝试了一些修改后的代码
private readonly object _userActivityLocker = new object();
private void btnSave_Click(object sender, EventArgs e)
{
if (System.Threading.Monitor.TryEnter(_userActivityLocker))
{
//note that any sub clicks will be ignored while we are here
try
{
DateTime dt = DateTime.Now;
Thread.Sleep(2000);
Debug.Print("FirstClick {0} Second Click {1}",dt.ToLongTimeString(), DateTime.Now.ToLongTimeString());
//here it is safe to call the save and you can disable the btn
Application.DoEvents();
}
finally
{
System.Threading.Monitor.Exit(_userActivityLocker);
//re-enable the btn if you disable it.
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我快速点击按钮(我用5次快速点击检查)时,已经触发了5个点击事件并显示了控制台窗口
FirstClick 1:30:22 PM第二次点击1:30:24 PM FirstClick 1:30:24 PM第二次点击1:30:26 PM FirstClick 1:30:26 PM第二次点击1:30:28 PM FirstClick 1:30: 28 PM第二次点击1:30:30 PM FirstClick 1:30:30 PM第二次点击1:30:32 PM
问题是你的程序在将数据保存到数据库时对世界是死的.用户的鼠标单击位于消息队列中,等待UI线程恢复生命.如果是,则不再禁用该按钮,以便触发Click事件.
您可以在重新启用按钮之前清空消息队列来解决此问题,以便在禁用按钮时处理单击:
private void button1_Click(object sender, EventArgs e) {
button1.Enabled = false;
// Save data to database
//...
System.Threading.Thread.Sleep(2000);
Application.DoEvents(); // Empty the message queue
if (!button1.IsDisposed) button1.Enabled = true;
}
Run Code Online (Sandbox Code Playgroud)
不要跳过IsDisposed测试,DoEvents很危险,因为它没有选择处理什么事件.当您的代码仍在运行时,它将很乐意让用户关闭主窗口.
但更好的解决方案是不要让你的UI线程像这样死掉.使用BackgroundWorker在工作线程上执行保存.这也将避免当你的保存需要超过几秒时,Windows提出的丑陋的"无响应"鬼窗口.它现在可能还没有这样做,但是从现在开始dbase成长的那一年.您可以在BGW的RunWorkerCompleted事件处理程序中重新启用该按钮.
通过启用,然后再次重新启用,就像您逃避的那样。这有什么问题吗?
public void SaveButton_Click(..., ...)
{
this.SaveButton.Enabled = false;
Save();
this.SaveButton.Enabled = true;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5046 次 |
| 最近记录: |