2010-02-18 92 views
2

我只是在Windows上开发我的第一个GUI应用程序。如何检查线程已完成,然后在C#/ WPF中填写进度条

我有一个WPF GUI到一个小的C#实用程序,它复制文件。当点击按钮进行复制时,我显然不希望GUI挂起。所以,我启动了一个新线程来运行复制文件的方法。我假设我到目前为止已经走上正轨,在C#中没有“更好”的方式来完成它了?

现在,我有一个ProgressBar,我想在线程完成时显示填充。 (目前运行状况良好)。如何检查复制完成的时间?

所以,到目前为止,我有:

Thread t = new Thread(delegate() 
{ 
    po.Organise(inputPath, outputPath, recursive); 
}); 

t.Start(); 

PBar.IsIndeterminate = true; 

而且我想以后的东西,就像:

if (t.Done) 
{ 
    PBar.Value = 100; 
} 
+0

请参阅此处以了解如何使用BackgroundWorker的示例:http://stackoverflow.com/questions/2200930/wpf-multithreading/2201008#2201008 – Heinzi 2010-02-18 16:33:03

回答

7

看一看的BackgroundWorker类。它支持RunWorkerCompletedProgressChanged等事件。
看一看here(这是关于一般线程+ backgroundworker,再次)。

+0

我尝试使用BackgroundWorker作为我的进度条,但我不断收到错误调用线程必须是STA,因为许多UI组件都需要这个。请参阅:http://stackoverflow.com/questions/25021838/indeterminate-progress-bar – 2014-07-31 15:03:58

0

你需要一个回调方法。 This应该让你开始。它使用AsyncCallback,这是解决此类问题的最佳方法。

我只是抬起头我一直在使用的一个项目为例,剥离出具体到我的应用程序的代码:

System.Windows.Forms.MethodInvoker mi = new System.Windows.Forms.MethodInvoker(delegate() 
{ 
    // Do your file copy here 
}); 

AsyncCallback ascb = new AsyncCallback(delegate(IAsyncResult ar) 
{ 
    this.Dispatcher.Invoke(new ThreadStart(delegate(){ 
    // set progressbar value to 100 here 
    }), null); 
}); 

mi.BeginInvoke(ascb, null); 
0

if (t.Done)块包装在自己的方法中。从工作线程的末尾调用此方法。

另外,您可能希望为工作线程指定一个名称,以便更容易在调试器中找到。

2

如前所述,考虑使用BackgroundWorker类。它是为这些情况而设计的,并且展示了适合你正在努力完成的事件。

使用ProgressChanged事件递增报告进度,并在任务完成时使用RunWorkerCompleted。检查MSDN页面以获取代码示例。

1

的建议:试着搜索"Progress Bar C#“堆栈溢出

我认为,有很多非常有用的帖子已经详细说明您需要做什么

0

快速和容易的黑客会。是只更新在你的线程您的匿名方法结束的UI显然,你不能直接更新它,但你可以使用Dispatcher.Invoke

Thread t = new Thread(delegate() 
{ 
    po.Organise(inputPath, outputPath, recursive); 
    Dispatcher.Invoke(new Action(()=>{PBar.Value = 100;}),null); 
}); 

t.Start(); 
0

作为一般的Windows编程的校长,你必须到m ake调用来从UI线程(通过消息泵处理消息的那个线程)更新UI。

在Windows窗体中,完成此操作的方式是通过在Control类上实现ISynchronizeInvoke interface,主要通过实施Invoke method

随着.NET 2.0的发布,人们意识到需要更好的机制来将呼叫编组到正确的上下文中。这就是SynchronizationContext进来的地方。

该类抽象出你将用于封送调用到不同上下文的接口,允许根据上下文进行特定的实现。

因此,无论Windows窗体是环境还是WPF,都可以在具有相同效果的上下文(编组呼叫)中以相同方式进行一次调用。

在您的特殊情况下,由于您使用的是闭包(匿名方法),因此您可以利用SynchronizationContext在Thread的调用站点上可用(通过静态Current property)以提供机制,从您的后台线程回调到UI线程:

// Get the synchronization context. 
// This is in the UI thread. 
SynchronizationContext sc = SynchronizationContext.Current; 

// Create the thread, but use the SynchronizationContext 
// in the closure to marshal the call back. 
Thread t = new Thread(delegate() 
{ 
    // Do your work. 
    po.Organise(inputPath, outputPath, recursive); 

    // Call back using the SynchronizationContext. 
    // Can call the Post method if you don't care 
    // about waiting for the result. 
    sc.Send(delegate() 
    { 
     // Fill the progress bar. 
     PBar.Value = 100; 
    }); 
}); 

// Make the progress bar indeterminate. 
PBar.IsIndeterminate = true; 

// Start the thread. 
t.Start(); 

注意,如果你不在乎等待回调到UI线程的结果,你可以对Post method通话相反,它将调用调用到UI线程,而不用等待那个调用完成。