在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:44:09  来源:igfitidea点击:

Updating Progress Bar from Thread in C#

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.Invokedelegate但没有用。

采纳答案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;
    }
}