在C#中从线程更新进度条
public class Consumer { Queue queue; Object lockObject; public Consumer(Queue queue, Object lockObject) { this.queue = queue; this.lockObject = lockObject; } public void consume(string filepath) { int item = 0; while (true) { lock (lockObject) { if (queue.Count == 0) { Monitor.PulseAll(lockObject); continue; } item = queue.Dequeue(); if (item == 0) { break; } //do some staff } } } } public class Producer { Queue queue; Object lockObject; public int ProgressPercent = 0; int TotalProducedElements = 0; public bool check1 = false; public Producer(Queue queue, Object lockObject) { this.queue = queue; this.lockObject = lockObject; } private bool IsPrime(int num) { if (num == 0) return true; num = Math.Abs(num); for (int i = 2; i <= Math.Sqrt(num); i++) if (num % i == 0) return false; return true; } public void produce(int target) { try { int seq = 0; while (seq++ < target) { lock (lockObject) { int item = seq; if (IsPrime(item)) { queue.Enqueue(item); } TotalProducedElements++; ProgressPercent = seq; if (queue.Count == 0) { Monitor.PulseAll(lockObject); } } } queue.Enqueue(0); } catch (Exception e) { } } } } private void Start_Click(object sender, EventArgs e) { Object lockObj = new object(); Queue queue = new Queue(); Producer p = new Producer(queue, lockObj); Consumer c = new Consumer(queue, lockObj); int target = int.Parse(TargetText.Text); string path = Path.Text; Thread Thread1 = new Thread(() => p.produce(target)); Thread Thread2 = new Thread(()=>c.consume(path)); Thread1.Start(); Thread2.Start(); progressBar1.Maximum = target; while(true) { if(p.ProgressPercent==0) { Thread.sleep(1000); } else { progressBar1.Value=p.ProgressPercent; } } }
我有两个类在同一个队列上工作。 一个产生一组整数,第二个是从队列中消耗整数。
在这一切中,我希望按该百分比更新我的进度条。 那么如何在不阻止我的GUI的情况下更新消费者的进度条?
注意我使用了progressbar.Invoke
和delegate
但是没有用。
你需要两件事。 首先显然是一个线程,另一个是调用者。
Invokers将允许您从线程内部更改窗口的控件。 这是一个例子:
Invoke((MethodInvoker)delegate { Label1.text = "asd"; }
线程像这样运行:
some_thread = new Thread (delegate() { { //some_thread code } }); some_thread.Start();
您还需要using System.Threading;
添加using System.Threading;
在文件的开头。
所以,最终的代码应如下所示:
some_thread = new Thread (delegate() { { for(;;) { Invoke((MethodInvoker)delegate { //update the progress bar here } } } }); some_thread.Start();
您可以使用BackgroundWorker(System.ComponentModel)轻松完成此任务。 看看: http : //www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo
明确:
while(true) { if(p.ProgressPercent==0) { Thread.sleep(1000); } else { progressBar1.Value=p.ProgressPercent; } }
更换:
ProgressPercent = seq;
至
UpdateProgres(seq);
加:
public void UpdateProgres(int _value) { if (InvokeRequired) { Invoke(new Action(UpdateProgres), _value); return; } progressBar1.Value = _value; }
总结您需要的function;
public void UpdateProgres(int _value) { if (InvokeRequired) { Invoke(new Action(UpdateProgres), _value); return; } progressBar1.Value = _value; }
或者需要锁定值。 例如;
while(true) { lock (p.ProgressPercent) { int _p = p.ProgressPercent; } if(_p==0) { Thread.sleep(1000); } else { progressBar1.Value=_p; } }