仅在后台操作很长时才显示进度

问题描述 投票:5回答:5

我正在开发一个C#操作,我想显示一个模态进度对话框,但只有当一个操作很长时(例如,超过3秒)。我在后台线程中执行我的操作。

问题是我事先并不知道该操作是长还是短。

IntelliJ这样的软件有一个计时器方法。如果操作时间超过x时间,则显示一个对话框。

你认为这是一个很好的模式来实现这个?

  • 用计时器等待UI线程,并在那里显示对话框?
  • 当我显示对话框时,我必须DoEvents()吗?
c# .net winforms background progress
5个回答
4
投票

我将在这里进行第一选择并进行一些修改:

首先在不同的线程中运行可能的长时间运行操作。 然后运行一个不同的线程,通过一个带有超时的等待句柄检查第一个状态,等待它完成。如果超时触发器显示进度条。

就像是:

private ManualResetEvent _finishLoadingNotifier = new ManualResetEvent(false);

private const int ShowProgressTimeOut = 1000 * 3;//3 seconds


private void YourLongOperation()
{
    ....

    _finishLoadingNotifier.Set();//after finish your work
}

private void StartProgressIfNeededThread()
{
    int result = WaitHandle.WaitAny(new WaitHandle[] { _finishLoadingNotifier }, ShowProgressTimeOut);

    if (result > 1)
    {
        //show the progress bar.
    } 
}

4
投票

这是我要做的:

1)使用BackgroundWorker。

2)在调用方法RunWorkerAsync之前,将当前时间存储在变量中。

3)在DoWork事件中,您需要调用ReportProgress。在ProgressChanged事件中,检查时间是否已超过三秒。如果是,请显示对话框。

以下是BackgroundWorker的MSDN示例:http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

注意:一般来说,我同意Ramhound的评论。只需始终显示进度。但是如果您不使用BackgroundWorker,我会开始使用它。它会让你的生活更轻松。


2
投票

假设你有DoPossiblyLongOperation()ShowProgressDialog()HideProgressDialog()方法,你可以使用TPL为你做繁重的工作:

var longOperation = new Task(DoPossiblyLongOperation).ContinueWith(() => myProgressDialog.Invoke(new Action(HideProgressDialog)));

if (Task.WaitAny(longOperation, new Task(() => Thread.Sleep(3000))) == 1)
    ShowProgressDialog();

0
投票

我会将进度对话框与后台活动分开,将我的UI逻辑与应用程序的其余部分分开。所以序列就是(这与IntelliJ的作用基本相同):

  1. UI启动后台操作(在BackgroundWorker中)并设置X秒的计时器
  2. 当计时器到期时,UI显示进度对话框(如果后台任务仍在运行)
  3. 后台任务完成后,取消定时器并关闭对话框(如果有)

使用计时器而不是单独的线程更具资源效率。


0
投票

推荐的非阻塞解决方案,没有新的线程:

try
{
   var t = DoLongProcessAsync();
   if (await Task.WhenAny(t, Task.Delay(1000)) != t) ShowProgress();
   await t;
}
finally
{
   HideProgress();
}
© www.soinside.com 2019 - 2024. All rights reserved.