Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在线程之间传递值?_C#_Multithreading - Fatal编程技术网

C# 如何在线程之间传递值?

C# 如何在线程之间传递值?,c#,multithreading,C#,Multithreading,我有一个带有窗体MainForm的windows窗体程序。按下一个按钮,我启动一个代码,在另一个线程上每0.5秒运行一次(脉冲)。我想从Pulse方法中修改很多东西,比如主窗体上的标签、进度条。这怎么可能? 所以我想知道,如何在线程和主窗体中与变量、值交互。相互修改等 点击foo按钮,我告诉我的脉动器开始。 Pulsator.Initialize() 这是脉动器等级: public static class Pulsator { private static Thread _worker

我有一个带有窗体MainForm的windows窗体程序。按下一个按钮,我启动一个代码,在另一个线程上每0.5秒运行一次(脉冲)。我想从Pulse方法中修改很多东西,比如主窗体上的标签、进度条。这怎么可能? 所以我想知道,如何在线程和主窗体中与变量、值交互。相互修改等

点击foo按钮,我告诉我的脉动器开始。 Pulsator.Initialize()

这是脉动器等级:

public static class Pulsator
{
    private static Thread _worker;

    public static void Initialize()
    {
        _worker = new Thread(Pulse);
        _worker.IsBackground = true;
        _worker.Start();
    }

    public static void Close()
    {
        if (_worker != null)
        {
            _worker.Abort();
            while (_worker.IsAlive || _worker.ThreadState != ThreadState.Stopped)
            {
               //closing
            }
        }
    }

    public static void Pulse()
    {
        if (_worker != null)
        {
            while (true)
            {
                SomeOtherClass.Pulse();
                Thread.Sleep(500);
            }
        }
        else
        {
            SomeOtherClass.Pulse(); // yeah I know this doesnt needed
        }
    }
}
另一类Pulse方法如下所示:

    public static void Pulse()
    {
        //here I will have several values, variables, and I want to show results,
        // values on my MainForm, like:
        Random random = new Random();
        MainForm.label1.Text = random.Next(123,321).ToString(); // I hope you know what I mean
    }

当然,这非常复杂,这只是一个愚蠢的例子。

通常,在WinForms中,在拥有控件底层非托管资源(窗口句柄)的线程之外修改可视控件的状态是不安全的。您必须使用该方法来计划在控件所属线程上执行修改。

C#2或更高版本(VS2005)具有匿名委托(C#3具有lambdas,这是相同想法的一个稍微整洁的版本)

这些允许线程使用一个函数启动,该函数可以“查看”周围范围中的变量。所以没有必要显式地传递任何信息。另一方面,线程可能会意外地依赖于它不应该依赖的内容(例如,其他线程中正在更改的变量)


为什么不使用System.Timers.Timer

例如:


正如其他人已经提到的,您必须使用Control.Invoke从后台线程更改UI控件

另一个选项是使用System.ComponentModel.BackgroundWorker(可在表单设计器工具箱中找到)。然后,您可以使用一个常规的forms计时器来调用RunWorkerAsync方法,并在DoWork事件处理程序中执行后台工作,该处理程序将从另一个线程自动调用


从那里,您可以通过调用ReportProgress将数据传递回主线程。这将在主线程中引发ProgressChanged事件,您可以在主线程中自由更新所有UI控件。

另外,请注意,调用thread.Abort会引发ThreadAbortException,您需要在Close方法System.Windows.Forms.Timer中处理该异常。Timer是执行UI工作的更好选择:
_worker = new Thread(delegate 
{
    // can refer to variables in enclosing scope(s).
});
        trainPassageTimer = new Timer(500);
        trainPassageTimer.AutoReset = true;
        trainPassageTimer.Elapsed += TimeElapsed;

        ...

        private void TimeElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
// Do stuff
// Remember to use BeginInvoke or Invoke to access Windows.Forms controls
        }