长时间操作时禁用按钮

时间:2016-10-03 15:44:41

标签: c# .net wpf

在长时间操作期间,我想禁用按钮并清除文本块。

在按钮上单击,在绘制屏幕之前完全处理事件,因此按钮永远不会被明显禁用

private bool btnEnabled = true;
public bool BtnEnabled
{
    get { return btnEnabled; }
    set
    {
        if (value == btnEnabled)
            return;
        btnEnabled = value;
        NotifyPropertyChanged("BtnEnabled");
    }
}
private string results = "start";
public string Results
{
    get { return results; }
    set
    {
        if (value == results)
            return;
        results = value;
        NotifyPropertyChanged("Results");
    }
}

private void btn_Click(object sender, RoutedEventArgs e)
{
    BtnEnabled = false;
    Results = string.Empty;
    // whould like to displany wait spinner
    LongProcess();
    BtnEnabled = true;
}
private void LongProcess()
{
    //database query
    System.Threading.Thread.Sleep(10000);
    Results = "this is the results";
}

如何在长时间活动期间停止按钮?

我遇到的问题是用户感到沮丧并开始点击,这些点击都在队列中并得到处理。

2 个答案:

答案 0 :(得分:0)

要回答您的具体问题,您可以使用类似的方法让UI处理消息(将按钮设置为禁用后):

Application.Current.Dispatcher.Invoke(
             DispatcherPriority.Background, 
             new Action(delegate { })
           );

或者更完整:

public void DoEvents()
{
    DispatcherFrame frame = new DispatcherFrame();
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
        new DispatcherOperationCallback(ExitFrame), frame);
    Dispatcher.PushFrame(frame);
}

public object ExitFrame(object f)
{
    ((DispatcherFrame)f).Continue = false;
    return null;
}

然后再次这不推荐(它相当于在Winforms上使用Application.DoEvents(),它有许多警告,应该像瘟疫一样避免,除非你知道你在做什么) 。不应该在UI线程上进行长时间的密集操作,或者如果它们不是CPU密集型的话,可以使用async/await

答案 1 :(得分:-1)

这就是我最终的结果

private async void btn_Click(object sender, RoutedEventArgs e)
{

    BtnEnabled = false;
    Results = string.Empty;
    // whould like to displany wait spinner
    //LongProcess();
    cts = new CancellationTokenSource();
    try
    {
        //cts.Cancel(); just for test
        string result = await WaitAsynchronouslyAsync(cts.Token);
        //string result = await WaitSynchronously();

        BtnEnabled = true;
        Results = result;
    }
    catch (OperationCanceledException)
    {
        Results = "Operation canceled";  // this is not called
    }
    cts = null;
}
// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window 
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync(CancellationToken ct)
{
    //DataBaseQuery();  // this just runs async
    //SqlCommand cmd = new SqlCommand();
    //await cmd.ExecuteScalarAsync(ct);
    await Task.Delay(10000);
    return "Finished";
}