如何在C#Winform中锁定应用程序GUI

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

Han*_*ant 5

问题是你的程序在将数据保存到数据库时对世界是死的.用户的鼠标单击位于消息队列中,等待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事件处理程序中重新启用该按钮.


Jos*_*ton 1

通过启用,然后再次重新启用,就像您逃避的那样。这有什么问题吗?

public void SaveButton_Click(..., ...)
{
    this.SaveButton.Enabled = false;
    Save();
    this.SaveButton.Enabled = true;
}
Run Code Online (Sandbox Code Playgroud)

  • @Akhil,这个解决方案有什么问题?你帮助我们不是为了帮助你。 (3认同)
  • @乔什,你不明白吗?他已经尝试过那些东西了。 (3认同)