WPF线程监控Process.Start并显示进度条

3

我正在尝试执行一个长时间运行的 Process.Start(),并在进程执行时在屏幕上显示一个圆形进度条。

我有以下代码:

Process p =
   Process.Start(longRunningProcess);

   // show the circular progress bar;

   ShowHideCirProgBar(true);

   // wait till the process ends execution

   p.WaitForExit();

   // hide the circular progress bar

   ShowHideCirProgBar(false);

我对线程模型不熟悉,不确定如何实现上述内容。非常感谢您的任何帮助。

谢谢, PJ


你想要实现什么? - undefined
所以,你想要一个进度指示器,但是不阻塞用户界面线程?你是否可以接受在外部进程完成之前让用户进行其他操作? - undefined
2个回答

4

很遗憾,调用:

p.WaitForExit();

将会导致您的程序执行阻塞,直到衍生的可执行文件退出。这将防止WPF处理其消息泵,进而防止进度条正确更新。

正常处理方法是禁用您的UI元素,然后在后台线程中生成进程并显示进度。当进程完成时,重新启用UI元素。使用.NET 4,可以这样实现:

// Add code to disable UI, if required
DisableUI();

// Show the circular progress bar;
ShowHideCirProgBar(true);

// Wait till the process ends execution in a background thread
var task = Task.Factory.StartNew( () =>     
    {
        Process p = Process.Start(longRunningProcess);
        p.WaitForExit();
    });

// Reenable the UI when the process completes...
task.ContinueWith( t =>
    {
        EnableUI();

        // hide the circular progress bar
        ShowHideCirProgBar(false);
    }, TaskScheduler.FromCurrentSynchronizationContext());

或者,您可以通过后台工作者(BackgroundWorker)完成同样的事情:

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s, e) =>
    {
        Process p = Process.Start(longRunningProcess);
        p.WaitForExit();
    };
bw.RunWorkerCompleted += (s, e) =>
    {
        EnableUI();

        // hide the circular progress bar
        ShowHideCirProgBar(false);
    };

// Add code to disable UI, if required
DisableUI();

// Show the circular progress bar;
ShowHideCirProgBar(true);
bw.RunWorkerAsync();

非常感谢Saurabh和Reed。让我立即尝试一下这些。我会很快回复结果的。 - undefined
嗨里德:它完全按照我想要的方式工作了。非常感谢你。我非常感激你的帮助。 - undefined

2
我认为你应该尝试使用后台工作者 (Background worker)。如果你希望在后台任务执行时实现响应式用户界面,这个类可以满足你的需求。如果你是线程概念的初学者,这个类非常基础、易于理解且效果出色,它还暴露了一些事件,你可以订阅这些事件来处理长时间运行的情况。请参考 Background worker
  class ThreadingWithBg
{
    BackgroundWorker bg = null;


    public ThreadingWithBg()
    {
        bg = new BackgroundWorker();
        bg.DoWork += new DoWorkEventHandler(bg_DoWork);
        bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);

    }

    void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {


     }

    void bg_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < 100000; i++)
        {
            Console.WriteLine(i.ToString());

        }
    }

    public void DoLongWork()
    {
        bg.RunWorkerAsync();

    }
}

不,我不希望在执行过程中用户进行任何操作。这就是为什么当循环进度条显示时,我也会禁用屏幕。从我的代码可以清楚地看到,它正在显示但没有旋转。 - undefined
Saurabh:请你能否为我的特定情况提供一些代码片段? - undefined
好的,请等一下,我会发布。 - undefined
嗨Reed:谢谢你的代码片段。我正在使用.NET 3.5,我不认为它包含了TPl。 - undefined
@P J:你应该在我的帖子上留下这个评论,这样我才能看到。话虽如此,如果你安装了Rx扩展,你就可以这样做:http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx(它附带了.NET 3.5的TPL)。你还可以使用BW - 我会把这个添加到我的帖子中供你参考... - undefined
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接