从另一个Thread更新MainWindow中的进度条
我知道这个问题已被问过几次,我花了一整天时间试图理解其他答案,但由于我对C#和WPF很新,所以到目前为止没有任何帮助。 我将尝试尽可能多地解释我的确切问题,这将直接帮助我。
在我的MainWindow.xaml中,我有一个进度条和一些按钮启动一个新线程和一个长计算:
现在在我的MainWindow.xaml.cs中:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { Thread thread = new Thread(new ParameterizedThreadStart(MyLongCalculation)); ParameterClass myParameters = new ParameterClass(); thread.Start(myParameters); } public void MyLongCalculations(object myvalues) { ParameterClass values = (ParameterClass)myvalues; //some calculations } } public class ParameterClass { //public variables... }
现在不知何故,我必须在我的方法MyLongCalculations中包含somethign,它将继续更新progressBar1
。 但是,我无法让它运作起来。 我知道这一切都很简单,但不幸的是,这是我目前使用C#的水平,所以我希望答案不要太复杂,尽可能详细。
背景工作者非常适合这一点。
试试这个:
/// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { public MainWindow() { // Initialize UI InitializeComponent(); // Process data ProcessDataAsync(new ParameterClass { Value = 20 }); } /// /// Processes data asynchronously /// /// private void ProcessDataAsync(ParameterClass myClass) { // Background worker var myWorker = new BackgroundWorker { WorkerReportsProgress = true, }; // Do Work myWorker.DoWork += delegate(object sender, DoWorkEventArgs e) { // Set result e.Result = MyLongCalculations(myClass); // Update progress (50 is just an example percent value out of 100) myWorker.ReportProgress(50); }; // Progress Changed myWorker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e) { myProgressBar.Value = e.ProgressPercentage; }; // Work has been completed myWorker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) { // Work completed, you are back in the UI thread. TextBox1.Text = (int) e.Result; }; // Run Worker myWorker.RunWorkerAsync(); } /// /// Performs calculations /// /// /// public int MyLongCalculations(ParameterClass myvalues) { //some calculations return (myvalues.Value*2); } } /// /// Custom class /// public class ParameterClass { public int Value { get; set; } }
您可以使用Dispatcher.BeginInvoke()在UI线程而不是工作线程上推送UI更改。 最重要的是 – 您需要访问与UI线程关联的Dispatcher,而不是您手动创建的工作线程。 所以我建议缓存Dispatcher.Current
,然后在工作线程中使用,你可以通过ParametersClass或只在类级别声明一个dispatchr字段。
public partial class MainWindow { private Dispatcher uiDispatcher; public MainWindow() { InitializeComponents(); // cache and then use in worker thread method this.uiDispatcher = uiDispatcher; } public void MyLongCalculations(object myvalues) { ParameterObject values = (ParameterObject)myvalues; this.uiDispatcher.BeginInvoke(/*a calculations delegate*/); } }
此外,如果您需要在某个服务/类(如ParametersClass
)中传递UI调度程序,我建议您看一下这个很好的SOpost ,它展示了如何通过一个接口来抽象它,能够同步/异步地推送UI更改,以便它将由调用者决定(基本上使用Invoke()
或BeginInvoke()
在UI消息管道中对委托进行排队)。
- C#正则表达式从youtube和vimeo获取videoID由url
- 使用附带事件与caliburn micro Message.Attach
- C#:HttpListener错误服务内容
- 是否可以在多个项目之间共享ResourceDictionary文件?
- Renci SSH.NET:是否可以创建包含不存在的子文件夹的文件夹
- 如何使用SampleGrabber为音频构建频谱/可视化工具?
- 只有在使用Unity的运行时值为非null时,如何注入属性?
- IIS6 WebService下Environment.GetFolderPath(Environment.SpecialFolder.ApplicationFolder)返回的错误路径
- 使用脚本启用到sql express的远程连接