在 C# 中从线程更新进度条
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13141280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Updating Progress Bar from Thread in C#
提问by Alyafey
public class Consumer
{
Queue<int> queue;
Object lockObject;
public Consumer(Queue<int> 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<int> queue;
Object lockObject;
public int ProgressPercent = 0;
int TotalProducedElements = 0;
public bool check1 = false;
public Producer(Queue<int> 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<int> queue = new Queue<int>();
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;
}
}
}
I have two classes working on same queue. one to produce a set of integers and the second is to consume that integers from queue.
我有两个班级在同一个队列上工作。一个产生一组整数,第二个是从队列中消耗这些整数。
And during all this I want to update my progress bar by that percentage. So how to update progress bar from consumer without blocking for my GUI?
在这一切期间,我想按那个百分比更新我的进度条。那么如何在不阻止我的 GUI 的情况下从消费者更新进度条呢?
Note I have used progressbar.Invokeand delegatebut didn't work.
注意我已经使用过progressbar.Invoke,delegate但没有用。
采纳答案by d33tah
You need two things. First is obviously a thread, the other is invoker.
你需要两件事。第一个显然是一个线程,另一个是调用者。
Invokers will let you change window's controls from inside of a thread. Here's the example:
调用程序将允许您从线程内部更改窗口的控件。这是示例:
Invoke((MethodInvoker)delegate
{
Label1.text = "asd";
}
Threads are ran like this:
线程是这样运行的:
some_thread = new Thread
(delegate()
{
{
//some_thread code
}
});
some_thread.Start();
You also need to add using System.Threading;at the beginning of the file.
您还需要using System.Threading;在文件开头添加。
So, the final code should look like this:
所以,最终的代码应该是这样的:
some_thread = new Thread
(delegate()
{
{
for(;;)
{
Invoke((MethodInvoker)delegate
{
//update the progress bar here
}
}
}
});
some_thread.Start();
回答by Fredrik
You could use a BackgroundWorker (System.ComponentModel) to accomplish this easily. Take a look at: http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo
您可以使用 BackgroundWorker (System.ComponentModel) 轻松完成此操作。看一看:http: //www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo
回答by VolkanCetinkaya
Clear:
清除:
while(true)
{
if(p.ProgressPercent==0)
{
Thread.sleep(1000);
}
else
{
progressBar1.Value=p.ProgressPercent;
}
}
Replace:
代替:
ProgressPercent = seq;
to
到
UpdateProgres(seq);
Add:
添加:
public void UpdateProgres(int _value)
{
if (InvokeRequired)
{
Invoke(new Action<int>(UpdateProgres), _value);
return;
}
progressBar1.Value = _value;
}
Summary your needed function;
总结你需要的功能;
public void UpdateProgres(int _value)
{
if (InvokeRequired)
{
Invoke(new Action<int>(UpdateProgres), _value);
return;
}
progressBar1.Value = _value;
}
Or need Lock the value. For Example;
或者需要锁定值。例如;
while(true)
{
lock (p.ProgressPercent)
{
int _p = p.ProgressPercent;
}
if(_p==0)
{
Thread.sleep(1000);
}
else
{
progressBar1.Value=_p;
}
}

