如何使用C#中的参数启动线程?
如何使用C#中的参数启动线程?
Answers:
是的:
Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
void MyParamObject(object myUrl){ //do stuff }
应具有参数类型object
ParameterizedThreadStart
并且可以从问题文本中清楚地知道,事实并非如此。
Thread构造函数的2个重载之一重载了ParameterizedThreadStart委托,该委托使您可以将单个参数传递给start方法。不幸的是,尽管它只允许使用一个参数,但这样做并不安全,因为它将其作为对象传递。我发现使用lambda表达式捕获相关参数并以强类型方式传递它们要容易得多。
尝试以下
public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
var t = new Thread(() => RealStart(param1, param2));
t.Start();
return t;
}
private static void RealStart(SomeType param1, SomeOtherType param2) {
...
}
Dim thr As New Thread(Sub() DoStuff(settings))
您可以使用lambda表达式
private void MyMethod(string param1,int param2)
{
//do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();
到目前为止,这是我能找到的最佳答案,它既快速又容易。
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
参数类型必须是一个对象。
编辑:
虽然这个答案不是正确的,但我还是建议不要使用这种方法。使用lambda表达式更容易阅读,并且不需要类型转换。看到这里:https : //stackoverflow.com/a/1195915/52551
Parameter
?
class Program
{
static void Main(string[] args)
{
Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));
t.Start("My Parameter");
}
static void ThreadMethod(object parameter)
{
// parameter equals to "My Parameter"
}
}
像这样使用lambda的简单方法..
Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();
或者您甚至delegate
可以ThreadStart
像这样使用...
ThreadStart ts = delegate
{
bool moreWork = DoWork("param1", "param2", "param3");
if (moreWork)
{
DoMoreWork("param4", "param5");
}
};
new Thread(ts).Start();
或者像这样使用VS 2019 .NET 4.5+甚至更清洁..
private void DoSomething(int param1, string param2)
{
//DO SOMETHING..
void ts()
{
if (param1 > 0) DoSomethingElse(param2, "param3");
}
new Thread(ts).Start();
//DO SOMETHING..
}
正如在这里的各种答案中已经提到的那样,Thread
当前的类(4.7.2)提供了几个构造函数和一个Start
带有重载的方法。
这些相关的构造函数是:
public Thread(ThreadStart start);
和
public Thread(ParameterizedThreadStart start);
可以选择一个ThreadStart
代表或一个ParameterizedThreadStart
代表。
相应的代表如下所示:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
可以看出,要使用的正确构造函数似乎是接受ParameterizedThreadStart
委托的构造函数,以便某些方法可以由线程启动符合委托的指定签名的方法。
初始化Thread
类的一个简单示例是
Thread thread = new Thread(new ParameterizedThreadStart(Work));
要不就
Thread thread = new Thread(Work);
相应方法的签名(Work
在此示例中称为)如下所示:
private void Work(object data)
{
...
}
剩下的就是启动线程。这可以通过使用以下任一方法来完成
public void Start();
要么
public void Start(object parameter);
虽然Start()
将启动线程并将其null
作为数据传递给方法,但是Start(...)
可以将任何东西传递Work
给线程的方法。
但是,这种方法存在一个大问题:传递给该Work
方法的所有内容都被转换为对象。这意味着必须在Work
方法内将其再次强制转换为原始类型,如以下示例所示:
public static void Main(string[] args)
{
Thread thread = new Thread(Work);
thread.Start("I've got some text");
Console.ReadLine();
}
private static void Work(object data)
{
string message = (string)data; // Wow, this is ugly
Console.WriteLine($"I, the thread write: {message}");
}
强制转换是您通常不希望执行的操作。
如果有人传递了不是字符串的其他东西怎么办?乍看起来似乎是不可能的(因为这是我的方法,因为我知道我在做什么,或者该方法是私有的,所以有人应该如何将任何东西传递给它?),由于各种原因,您可能最终会遇到这种情况。由于某些情况可能不是问题,其他情况则是。在这种情况下InvalidCastException
,您可能会得到一个可能根本不会注意到的,因为它只是终止了线程。
作为解决方案,您希望获得一个通用ParameterizedThreadStart
委托,例如要传递到方法中的数据类型ParameterizedThreadStart<T>
在哪里。不幸的是,这样的东西不存在(还?)。T
Work
但是,有针对此问题的建议解决方案。它涉及创建一个类,该类既包含要传递给线程的数据,又包含表示worker方法的方法,如下所示:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
使用这种方法,您将像这样启动线程:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
因此,以这种方式,您只需避免进行转换,并具有将数据提供给线程的类型安全方式;-)
private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
message.Length
不可能等等)
if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }
。不管怎么说,而不是用螺纹方法,我发现更舒服一点使用Tasks<T>
,例如像tasks.Add(Task.Run(() => Calculate(par1, par2, par3)))
,看到我的回答如下(stackoverflow.com/a/59777250/7586301)
您可以使用ParametrizedThreadStart委托:
string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);
您可以使用BackgroundWorker RunWorkerAsync方法并传递您的值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
int x = 10;
Thread t1 =new Thread(new ParameterizedThreadStart(order1));
t1.IsBackground = true;//i can stope
t1.Start(x);
Thread t2=new Thread(order2);
t2.Priority = ThreadPriority.Highest;
t2.Start();
Console.ReadKey();
}//Main
static void order1(object args)
{
int x = (int)args;
for (int i = 0; i < x; i++)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(i.ToString() + " ");
}
}
static void order2()
{
for (int i = 100; i > 0; i--)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(i.ToString() + " ");
}
}`enter code here`
}
}
我建议使用Task<T>
代替Thread
; 它允许多个参数并执行得很好。
这是一个工作示例:
public static void Main()
{
List<Task> tasks = new List<Task>();
Console.WriteLine("Awaiting threads to finished...");
string par1 = "foo";
string par2 = "boo";
int par3 = 3;
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() => Calculate(par1, par2, par3)));
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine("All threads finished!");
}
static bool Calculate1(string par1, string par2, int par3)
{
lock(_locker)
{
//...
return true;
}
}
// if need to lock, use this:
private static Object _locker = new Object();"
static bool Calculate2(string par1, string par2, int par3)
{
lock(_locker)
{
//...
return true;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
int x = 10;
Thread t1 =new Thread(new ParameterizedThreadStart(order1));
t1.Start(x);
Thread t2=new Thread(order2);
t2.Priority = ThreadPriority.Highest;
t2.Start();
Console.ReadKey();
}//Main
static void order1(object args)
{
int x = (int)args;
for (int i = 0; i < x; i++)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(i.ToString() + " ");
}
}
static void order2()
{
for (int i = 100; i > 0; i--)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(i.ToString() + " ");
}
}
}
}