显示进度条,而这样做在C#中一些工作? [英] Display progress bar while doing some work in C#?

查看:157
本文介绍了显示进度条,而这样做在C#中一些工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想显示一个进度条,同时做了一些工作,但会挂起用户界面和进度条将不会更新。

I want to display a progress bar while doing some work, but that would hang the UI and the progress bar won't update.

我有一个WinForm ProgressForm与进度,将继续无限期地在选取框时尚。

I have a WinForm ProgressForm with a ProgressBar that will continue indefinitely in a marquee fashion.

using(ProgressForm p = new ProgressForm(this))
{
//Do Some Work
}

现在有许多办法来解决这个问题,如使用的BeginInvoke ,等待任务完成,并调用 EndInvoke会。或者使用BackgroundWorker或线程。

Now there are many ways to solve the issue, like using BeginInvoke, wait for the task to complete and call EndInvoke. Or using the BackgroundWorker or Threads.

我有与EndInvoke会有些问题,尽管这不是问题。问题是,这是最好的,你用它来处理这种情况下,你必须表明程序工作,而不是反应迟钝用户,以及你如何处理与简单code可能是有效率的最简单的方法并不会泄漏,并且能够更新GUI。

I am having some issues with the EndInvoke, though that's not the question. The question is which is the best and the simplest way you use to handle such situations, where you have to show the user that the program is working and not unresponsive, and how do you handle that with simplest code possible that is efficient and won't leak, and can update the GUI.

如同的BackgroundWorker 需要具有多种功​​能,声明成员变量,等你也需要再抱一个参考进度表,并进行处理。

Like BackgroundWorker needs to have multiple functions, declare member variables, etc. Also you need to then hold a reference to the ProgressBar Form and dispose of it.

修改的BackgroundWorker 不是问题的答案,因为这可能是我不明白的进度通知,这意味着就没有打电话给ProgressChanged为DoWork的是外部函数调用一次,但我需要保持调用 Application.DoEvents(); 进度条不断旋转

Edit: BackgroundWorker is not the answer because it may be that I don't get the progress notification, which means there would be no call to ProgressChanged as the DoWork is a single call to an external function, but I need to keep call the Application.DoEvents(); for the progress bar to keep rotating.

赏金是这个问题的最佳code解决方案。我只需要调用Application.DoEvents(),以便马凯进度条会的工作,而工人功能可在主线程,它不返回任何进展的通知。我从来没有需要.NET神奇code自动报告进展情况,我只是需要比一个更好的解决方案:

The bounty is for the best code solution for this problem. I just need to call Application.DoEvents() so that the Marque progress bar will work, while the worker function works in the Main thread, and it doesn't return any progress notification. I never needed .NET magic code to report progress automatically, I just needed a better solution than :

Action<String, String> exec = DoSomethingLongAndNotReturnAnyNotification;
IAsyncResult result = exec.BeginInvoke(path, parameters, null, null);
while (!result.IsCompleted)
{
  Application.DoEvents();
}
exec.EndInvoke(result);

这是保持进度条活(指不结冰,但刷新了劳斯莱斯)

that keeps the progress bar alive (means not freezing but refreshes the marque)

推荐答案

在我看来,你是在至少一个错误的假设之上运行。

在你的问题,你说这样的:

In your question you say this:

BackgroundWorker的不是答案   因为这可能是我没有得到的   进度通知,这意味着   有将是没有呼叫   ProgressChanged因为DoWork的是   外部函数调用一次。   。

BackgroundWorker is not the answer because it may be that I don't get the progress notification, which means there would be no call to ProgressChanged as the DoWork is a single call to an external function . . .

其实,这不要紧,你是否调用 ProgressChanged 事件或不可以。该事件的全部目的是暂时回控制权转移到GUI线程来进行更新,不知怎的,反映工作进展情况的的BackgroundWorker 正在做。 如果您只是显示字幕进度条,它实际上是毫无意义的提高 ProgressChanged 事件在所有。进度条会继续下去,只要它显示旋转,因为从GUI在一个单独的线程的BackgroundWorker 正在做的工作

Actually, it does not matter whether you call the ProgressChanged event or not. The whole purpose of that event is to temporarily transfer control back to the GUI thread to make an update that somehow reflects the progress of the work being done by the BackgroundWorker. If you are simply displaying a marquee progress bar, it would actually be pointless to raise the ProgressChanged event at all. The progress bar will continue rotating as long as it is displayed because the BackgroundWorker is doing its work on a separate thread from the GUI.

(在一个侧面说明,的DoWork 是一个事件,这意味着它是没有的只是的外部函数调用一次 ;您可以根据需要添加尽可能多的处理程序;而且每个处理程序最多可以包含函数调用,因为它喜欢)

(On a side note, DoWork is an event, which means that it is not just "a single call to an external function"; you can add as many handlers as you like; and each of those handlers can contain as many function calls as it likes.)

要我来说,它听起来像你认为的唯一的方式为图形用户界面更新是通过调用 Application.DoEvents

To me it sounds like you believe that the only way for the GUI to update is by calling Application.DoEvents:

我需要保持调用   Application.DoEvents();为了   进度条不断旋转。

I need to keep call the Application.DoEvents(); for the progress bar to keep rotating.

这不是在多线程情况下真正;如果您使用的BackgroundWorker ,GUI会继续响应(在自己的线程),而的BackgroundWorker 做什么已经连接到它的的DoWork 事件。下面是如何这可能会为你工作了一个简单的例子。

This is not true in a multithreaded scenario; if you use a BackgroundWorker, the GUI will continue to be responsive (on its own thread) while the BackgroundWorker does whatever has been attached to its DoWork event. Below is a simple example of how this might work for you.

private void ShowProgressFormWhileBackgroundWorkerRuns() {
    // this is your presumably long-running method
    Action<string, string> exec = DoSomethingLongAndNotReturnAnyNotification;

    ProgressForm p = new ProgressForm(this);

    BackgroundWorker b = new BackgroundWorker();

    // set the worker to call your long-running method
    b.DoWork += (object sender, DoWorkEventArgs e) => {
        exec.Invoke(path, parameters);
    };

    // set the worker to close your progress form when it's completed
    b.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs e) => {
        if (p != null && p.Visible) p.Close();
    };

    // now actually show the form
    p.Show();

    // this only tells your BackgroundWorker to START working;
    // the current (i.e., GUI) thread will immediately continue,
    // which means your progress bar will update, the window
    // will continue firing button click events and all that
    // good stuff
    b.RunWorkerAsync();
}

3。不能在同一线程中运行的两种方法在同一时间

您这样说:

3. You can't run two methods at the same time on the same thread

You say this:

我只需要调用   Application.DoEvents(),使得   马凯进度条会工作,而   工人功能可在主   线 。 。

I just need to call Application.DoEvents() so that the Marque progress bar will work, while the worker function works in the Main thread . . .

什么你问的是根本就不是真正的。 主线程Windows窗体应用程序的GUI线程,而如果是忙于您的长时间运行的方法中,不提供视觉更新。如果你相信,否则,我怀疑你误解了的BeginInvoke 的作用:它启动一个委托的在一个单独的线程。事实上,你已经包括在你的问题的例子code调用 Application.DoEvents exec.BeginInvoke exec.EndInvoke 是多余的;你实际上是调用 Application.DoEvents 重复地从GUI线程,这将是无论如何更新。 (如果你发现了,否则,我怀疑这是因为你叫 exec.EndInvoke 向右走,这阻止当前线程,直到方法完成。)

What you're asking for is simply not real. The "main" thread for a Windows Forms application is the GUI thread, which, if it's busy with your long-running method, is not providing visual updates. If you believe otherwise, I suspect you misunderstand what BeginInvoke does: it launches a delegate on a separate thread. In fact, the example code you have included in your question to call Application.DoEvents between exec.BeginInvoke and exec.EndInvoke is redundant; you are actually calling Application.DoEvents repeatedly from the GUI thread, which would be updating anyway. (If you found otherwise, I suspect it's because you called exec.EndInvoke right away, which blocked the current thread until the method finished.)

所以,是的,你要找的答案是使用的BackgroundWorker

So yes, the answer you're looking for is to use a BackgroundWorker.

您的可以的使用的BeginInvoke ,而是调用 EndInvoke会从GUI线程(这将阻止它,如果该方法还没有完成),传递一个的AsyncCallback 参数给你的的BeginInvoke 电话(而不是只是路过),并在回调关闭进度表。但请注意,如果你这样做,你将不得不调用该关闭的GUI线程的进度表的方法,否则你会试图关闭的一种形式,它是一个GUI功能,从非GUI线程。但实际上,使用的所有缺陷的BeginInvoke / EndInvoke会已处理的的你的的BackgroundWorker 类,即使你认为这是.NET神奇code(对我来说,这只是一个直观和有用的工具)。

You could use BeginInvoke, but instead of calling EndInvoke from the GUI thread (which will block it if the method isn't finished), pass an AsyncCallback parameter to your BeginInvoke call (instead of just passing null), and close the progress form in your callback. Be aware, however, that if you do that, you're going to have to invoke the method that closes the progress form from the GUI thread, since otherwise you'll be trying to close a form, which is a GUI function, from a non-GUI thread. But really, all the pitfalls of using BeginInvoke/EndInvoke have already been dealt with for you with the BackgroundWorker class, even if you think it's ".NET magic code" (to me, it's just an intuitive and useful tool).

这篇关于显示进度条,而这样做在C#中一些工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆