如何运行多线程应用程序?

时间:2022-06-29 20:59:46

These codes generates us this error:

这些代码会生成这个错误:

Cross-thread operation not valid: Control 'progressBar2' accessed from a thread other than the thread it was created on.

跨线程操作无效:控制'progressBar2'从其创建的线程以外的线程访问。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ThreadingTest1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        ThreadStart ts1;
        ThreadStart ts2;
        Thread t1;
        Thread t2;

        private void btnStart_Click(object sender, EventArgs e)
        {
            ts1 = new ThreadStart(z1);
            ts2 = new ThreadStart(z2);

            t1 = new Thread(ts1);
            t2 = new Thread(ts2);

            t1.Start(); 
            t2.Start();

            btnStart.Enabled = false;
        }

        public void z1()
        {

            for (int i = 1; i < 60; ++i)
            {
                progressBar1.Value += 1;
                for (int j = 1; j < 10000000; ++j)
                {
                    j += 1;
                }
            }
        }

        public void z2()
        {
            for (int k = 1; k < 100; ++k)
            {
                progressBar2.Value += 1;
                for (int j = 1; j < 25000000; ++j)
                {
                    j += 1;
                }
            }
        }

        private void btnstop_Click(object sender, EventArgs e)
        {
            t1.Suspend(); 
            t2.Suspend();
        }

        private void btnContinue_Click(object sender, EventArgs e)
        {
            t1.Resume(); 
            t2.Resume();

        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            if (t1.IsAlive)
            {
                MessageBox.Show("Çalışan threadler var program sonlanamaz.");
            }
            else
            {
                this.Close();
            } 

        }
    }
}

3 个解决方案

#1


You can't access a UI control in a thread other than the UI thread responsible for that control.

您无法访问负责该控件的UI线程以外的线程中的UI控件。

See the WinForms page in my threading tutorial and also search for tutorials on BackgroundWorker, a component introduced in .NET 2.0 which makes life much easier (particularly for progress bars).

请参阅我的线程教程中的WinForms页面,并在BackgroundWorker上搜索教程,后者是.NET 2.0中引入的一个组件,它使生活更加轻松(特别是对于进度条)。

Additionally, I'd try to avoid using Thread.Suspend/Resume, preferring a more co-operative approach (e.g. with Monitor.Wait/Pulse). That allows you to avoid suspending a thread while it holds a lock, etc.

另外,我试图避免使用Thread.Suspend / Resume,更喜欢更合作的方法(例如使用Monitor.Wait / Pulse)。这样可以避免在持有锁的情况下挂起线程等。

#2


For both z1 and z2 do this: Add a zSafe() Call zSafe() within z() after InvokeRequired check.

对于z1和z2,执行以下操作:在InvokeRequired检查后,在z()内添加zSafe()调用zSafe()。

public void z1Safe()
        {

            for (int i = 1; i < 60; ++i)
            {
                progressBar1.Value += 1;
                for (int j = 1; j < 10000000; ++j)
                {
                    j += 1;
                }
            }
        }

        public void z1()
        {

            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate { z1Safe(); });
            }
            else
                z1Safe();
        }

I just implemented a similar solution in my windows form for asyn del call and it works fine.

我刚刚在我的Windows窗体中为asyn del调用实现了一个类似的解决方案,它工作正常。

#3


Cross thread exceptions are very common when you are working on a multithread application and it happens when you try to invoke a member of a control in a thread other than its own thread.To avoid that you can check InvokeRequired property of that control and invoke a delegate in its own thread or use a BackgroundWorker to run a process in background (another thread) and handle its events,When you handle BackgroundWorker events ,event handler methods will run on the main thread so there's no need to invoke a delegate.

当您处理多线程应用程序时,跨线程异常非常常见,当您尝试在除其自己的线程之外的线程中调用控件的成员时,它会发生。为了避免这种情况,您可以检查该控件的InvokeRequired属性并调用委托自己的线程或使用BackgroundWorker在后台运行进程(另一个线程)并处理其事件,当您处理BackgroundWorker事件时,事件处理程序方法将在主线程上运行,因此不需要调用委托。

Here you can find some information about BackgroundWorker

在这里,您可以找到有关BackgroundWorker的一些信息

#1


You can't access a UI control in a thread other than the UI thread responsible for that control.

您无法访问负责该控件的UI线程以外的线程中的UI控件。

See the WinForms page in my threading tutorial and also search for tutorials on BackgroundWorker, a component introduced in .NET 2.0 which makes life much easier (particularly for progress bars).

请参阅我的线程教程中的WinForms页面,并在BackgroundWorker上搜索教程,后者是.NET 2.0中引入的一个组件,它使生活更加轻松(特别是对于进度条)。

Additionally, I'd try to avoid using Thread.Suspend/Resume, preferring a more co-operative approach (e.g. with Monitor.Wait/Pulse). That allows you to avoid suspending a thread while it holds a lock, etc.

另外,我试图避免使用Thread.Suspend / Resume,更喜欢更合作的方法(例如使用Monitor.Wait / Pulse)。这样可以避免在持有锁的情况下挂起线程等。

#2


For both z1 and z2 do this: Add a zSafe() Call zSafe() within z() after InvokeRequired check.

对于z1和z2,执行以下操作:在InvokeRequired检查后,在z()内添加zSafe()调用zSafe()。

public void z1Safe()
        {

            for (int i = 1; i < 60; ++i)
            {
                progressBar1.Value += 1;
                for (int j = 1; j < 10000000; ++j)
                {
                    j += 1;
                }
            }
        }

        public void z1()
        {

            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate { z1Safe(); });
            }
            else
                z1Safe();
        }

I just implemented a similar solution in my windows form for asyn del call and it works fine.

我刚刚在我的Windows窗体中为asyn del调用实现了一个类似的解决方案,它工作正常。

#3


Cross thread exceptions are very common when you are working on a multithread application and it happens when you try to invoke a member of a control in a thread other than its own thread.To avoid that you can check InvokeRequired property of that control and invoke a delegate in its own thread or use a BackgroundWorker to run a process in background (another thread) and handle its events,When you handle BackgroundWorker events ,event handler methods will run on the main thread so there's no need to invoke a delegate.

当您处理多线程应用程序时,跨线程异常非常常见,当您尝试在除其自己的线程之外的线程中调用控件的成员时,它会发生。为了避免这种情况,您可以检查该控件的InvokeRequired属性并调用委托自己的线程或使用BackgroundWorker在后台运行进程(另一个线程)并处理其事件,当您处理BackgroundWorker事件时,事件处理程序方法将在主线程上运行,因此不需要调用委托。

Here you can find some information about BackgroundWorker

在这里,您可以找到有关BackgroundWorker的一些信息