如何在类/线程之间传递变量 [英] How do you pass variable between classes/threads

查看:93
本文介绍了如何在类/线程之间传递变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,对于大多数人来说,这可能是一个容易回答的问题,但我是C#编程新手,并不习惯格式化。不幸的是,对于我想要做的事情,我相信C#将是最好的方法。



总体目标是拥有一个前端(通过WinForms的GUI),只需点击一下按钮,我就可以在远程桌面上启动或停止服务。我遇到的问题是让线程工作并将桌面位置的名称传递回另一个类的线程。



下面是我的代码以一种普遍的方式。我遇到困难的部分是在button4_Click内。每个按钮上的文本将代表我正在启动或停止的服务的位置,这就是为什么将它用作传递给TS_Start函数的属性的理想选择。



也许我说这一切都错了,任何输入都会很棒!谢谢!



Hello, This is probably an easy question for most to answer but I am new to C# programming and am not used to the formatting. Unfortunately, for what I am trying to do I believe C# will be the best approach.

The overall goal is to have a front end (GUI via WinForms) that with a click of a button I can start or stop a service on a remote desktop. The issue I have run into is getting threading to work and passing the name of the location of the desktop back to the thread in a different class.

Below is my code in a generalized fashion. The section I am having difficulty with is within the button4_Click. The text on each button would represent the location of the service I am starting or stopping which is why it is ideal to use it as the property passed to the TS_Start function.

Maybe I am going about this all wrong, any input would be great! Thanks!

namespace Phoenix
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>

        public string Start = "Attempting to start ";
        public string Stop = "Attempting to stop ";
        public static TimeSpan timer1 = new TimeSpan(0, 2, 0);

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
		
        public static void GEN_Start(string location)
        {
            ServiceController svc = new ServiceController("Service Name", location);
            svc.Start();
            svc.WaitForStatus(ServiceControllerStatus.Running, timer1);
            if (svc.Status == ServiceControllerStatus.Running)
            {
				// Service Running do stuff
            }
            else
            {
				// Service not Running do stuff or time-out
            }
        }
    }
	
	public partial class Form1 : Form
    {
        public Form1()
        {
            ConnectionOptions options = new ConnectionOptions();
            options.Password = "username";
            options.Username = "password";
            InitializeComponent();
        }
		private void button4_Click(object sender, EventArgs e)
        {
			// Check if user is sure
            Form2 frm = new Form2();
            DialogResult result = frm.ShowDialog();
            if (result == DialogResult.Yes)
            {
				// Start thread
                Thread START=new Thread(new ThreadStart(Program.GEN_Start(button4.Text)));
                START.Start(button4.Text);
            }
        }
	}

	public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // YES
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // NO
        }
    }	
}

推荐答案

那里是线程之间传递数据的许多方面。第一个重要方面是将通知从非UI线程传递到UI线程。您不能从非UI线程调用与UI相关的任何内容。相反,您需要使用 Invoke System.Windows.Threading的方法。 Dispatcher (对于Forms或WPF)或 System.Windows.Forms.Control (仅限表单)。



您将在我过去的答案中找到有关其工作原理和代码示例的详细说明:

Control.Invoke()与Control.BeginInvoke()

使用Treeview扫描仪和MD5的问题



另请参阅有关线程的更多参考资料:

主要的.NET事件线程

如何让keydown事件在不同的线程上运行i n vb.net

在启用禁用+多线程后控制事件未触发



另请参阅我的其他答案中的参考:主线程上的.NET事件 [ ^ ]。



请注意以上与阻止集合相关的参考(用于线程通信和线程间调用的简单阻塞队列 [ ^ ])。我上面解释的调用机制仅针对UI框架/库实现。它不适用于某些任意线程;你需要创建一个类似的机制。我的阻止收集文章解释了它,我的替代解决方案推荐现有的.NET BCL类 System.Collections.Concurrent.BlockingCollection



我提出的线程包装器技术涵盖了以异步方式传递数据的其他方面,特别是在线程初始化(但不仅仅是)。请查看我过去的答案:

使代码线程安全 [ ^ ] ,

如何通过ref参数到线程 [ ^ ],

更改线程(生产者)启动后的参数 [ ^ ],

C#中的MultiThreading [ ^ ]。



-SA
There is a number of aspects of passing data between threads. First important aspect is passing notifications from a non-UI thread to, specifically, to a UI thread. You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke(),
Problem with Treeview Scanner And MD5.

See also more references on threading:
.NET event on main thread,
How to get a keydown event to operate on a different thread in vb.net,
Control events not firing after enable disable + multithreading.

See also the reference in my other answer: .NET event on main thread[^].

Note the reference above related to blocking collection (Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^]). The invocation mechanism I explained above is implemented only for the UI frameworks/libraries. It is inapplicable to some arbitrary threads; you would need to create a similar mechanism. My article of blocking collection explains it, and an alternative solution to mine recommends existing .NET BCL class System.Collections.Concurrent.BlockingCollection.

Other aspects of passing data in asynchronous way, especially at thread initialization (but not only), are covered by the technique of thread wrappers I put forward. Please see my past answers:
Making Code Thread Safe[^],
How to pass ref parameter to the thread[^],
Change parameters of thread (producer) after it is started[^],
MultiThreading in C#[^].

—SA


这篇关于如何在类/线程之间传递变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆