Làm thế nào để bạn bắt đầu một chủ đề với các tham số trong C #?
Làm thế nào để bạn bắt đầu một chủ đề với các tham số trong C #?
Câu trả lời:
Vâng :
Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
void MyParamObject(object myUrl){ //do stuff }
nên có loại tham sốobject
ParameterizedThreadStart
và rõ ràng từ văn bản câu hỏi, đó có lẽ không phải là trường hợp.
Một trong 2 tình trạng quá tải của hàm tạo Thread đưa ra một đại biểu ParameterizedThreadStart cho phép bạn truyền một tham số duy nhất cho phương thức start. Thật không may, mặc dù nó chỉ cho phép một tham số duy nhất và nó làm như vậy theo cách không an toàn vì nó chuyển nó dưới dạng đối tượng. Tôi thấy việc sử dụng biểu thức lambda dễ dàng hơn nhiều để nắm bắt các tham số có liên quan và chuyển chúng theo kiểu được gõ mạnh.
Hãy thử như sau
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))
Bạn có thể sử dụng biểu thức lambda
private void MyMethod(string param1,int param2)
{
//do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();
đây là câu trả lời tốt nhất tôi có thể tìm thấy, nó nhanh và dễ dàng.
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
Loại tham số phải là một đối tượng.
BIÊN TẬP:
Trong khi câu trả lời này không chính xác, tôi khuyên bạn nên chống lại phương pháp này. Sử dụng biểu thức lambda dễ đọc hơn nhiều và không yêu cầu truyền kiểu. Xem tại đây: 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"
}
}
Cách đơn giản sử dụng lambda như vậy ..
Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();
HOẶC bạn thậm chí có thể delegate
sử dụng ThreadStart
như vậy ...
ThreadStart ts = delegate
{
bool moreWork = DoWork("param1", "param2", "param3");
if (moreWork)
{
DoMoreWork("param4", "param5");
}
};
new Thread(ts).Start();
HOẶC sử dụng VS 2019 .NET 4.5+ thậm chí còn sạch hơn như vậy ..
private void DoSomething(int param1, string param2)
{
//DO SOMETHING..
void ts()
{
if (param1 > 0) DoSomethingElse(param2, "param3");
}
new Thread(ts).Start();
//DO SOMETHING..
}
Sử dụng ParametrizedThreadStart
.
Như đã được đề cập trong các câu trả lời khác nhau ở đây, Thread
lớp hiện tại (4.7.2) cung cấp một số hàm tạo và một Start
phương thức với tình trạng quá tải.
Những nhà xây dựng có liên quan cho câu hỏi này là:
public Thread(ThreadStart start);
và
public Thread(ParameterizedThreadStart start);
trong đó có một ThreadStart
đại biểu hoặc một ParameterizedThreadStart
đại biểu.
Các đại biểu tương ứng trông như thế này:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
Vì vậy, như có thể thấy, hàm tạo chính xác để sử dụng dường như là hàm lấy một ParameterizedThreadStart
đại biểu để một số phương thức phù hợp với chữ ký được chỉ định của đại biểu có thể được bắt đầu bởi luồng.
Một ví dụ đơn giản để kích hoạt Thread
lớp học sẽ là
Thread thread = new Thread(new ParameterizedThreadStart(Work));
hoặc chỉ
Thread thread = new Thread(Work);
Chữ ký của phương thức tương ứng (được gọi Work
trong ví dụ này) trông như thế này:
private void Work(object data)
{
...
}
Những gì còn lại là bắt đầu chuỗi. Điều này được thực hiện bằng cách sử dụng một trong hai
public void Start();
hoặc là
public void Start(object parameter);
Trong khi Start()
sẽ bắt đầu luồng và truyền null
dưới dạng dữ liệu cho phương thức, Start(...)
có thể được sử dụng để truyền bất cứ thứ gì vào Work
phương thức của luồng.
Tuy nhiên, có một vấn đề lớn với cách tiếp cận này: Mọi thứ được truyền vào Work
phương thức đều được đưa vào một đối tượng. Điều đó có nghĩa là trong Work
phương thức nó phải được chuyển sang loại ban đầu như trong ví dụ sau:
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}");
}
Đúc là điều bạn thường không muốn làm.
Điều gì xảy ra nếu ai đó vượt qua một thứ khác không phải là một chuỗi? Vì điều này ban đầu dường như không thể (vì đó là phương pháp của tôi, tôi biết tôi làm gì hoặc Phương pháp này là riêng tư, làm thế nào để ai đó có thể chuyển bất cứ điều gì cho nó? ) Bạn có thể kết thúc chính xác với trường hợp đó vì nhiều lý do . Vì một số trường hợp có thể không phải là một vấn đề, những người khác là. Trong những trường hợp như vậy, bạn có thể sẽ kết thúc với một InvalidCastException
cái mà bạn có thể sẽ không nhận thấy bởi vì nó chỉ đơn giản là chấm dứt chuỗi.
Là một giải pháp mà bạn mong đợi để có được một ParameterizedThreadStart
đại biểu chung giống như ParameterizedThreadStart<T>
nơi T
sẽ là loại dữ liệu bạn muốn truyền vào Work
phương thức. Thật không may, một cái gì đó như thế này không tồn tại (chưa?).
Tuy nhiên, có một giải pháp được đề xuất cho vấn đề này. Nó liên quan đến việc tạo một lớp chứa cả hai, dữ liệu được truyền đến luồng cũng như phương thức đại diện cho phương thức worker như thế này:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
Với phương pháp này, bạn sẽ bắt đầu chuỗi như thế này:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
Vì vậy, theo cách này, bạn chỉ cần tránh truyền xung quanh và có một cách an toàn để cung cấp dữ liệu cho một chuỗi ;-)
private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
message.Length
là không thể và v.v.)
if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }
. Dù sao, thay vì sử dụng phương pháp phân luồng của bạn, tôi thấy thoải mái hơn khi sử dụng Tasks<T>
, ví dụ như tasks.Add(Task.Run(() => Calculate(par1, par2, par3)))
xem câu trả lời của tôi bên dưới ( stackoverflow.com/a/59777250/7586602 )
Tôi đã có vấn đề trong các tham số thông qua. Tôi đã truyền số nguyên từ một vòng lặp for cho hàm và hiển thị nó, nhưng nó luôn cho ra các kết quả khác nhau. như (1,2,2,3) (1,2,3,3) (1,1,2,3), v.v ... với đại biểu ParametrienedThreadStart .
mã đơn giản này làm việc như một nét duyên dáng
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
Các ParameterizedThreadStart
tham số mất một. Bạn có thể sử dụng nó để gửi một tham số hoặc một lớp tùy chỉnh có chứa một số thuộc tính.
Một phương thức khác là đặt phương thức mà bạn muốn bắt đầu như một thành viên thể hiện trong một lớp cùng với các thuộc tính cho các tham số mà bạn muốn đặt. Tạo một thể hiện của lớp, đặt các thuộc tính và bắt đầu luồng chỉ định thể hiện và phương thức và phương thức có thể truy cập các thuộc tính.
Bạn có thể sử dụng một đại biểu ParametrienedThreadStart :
string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);
Bạn có thể sử dụng phương thức BackgroundWorker RunWorkerAsync và chuyển vào giá trị của bạn.
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`
}
}
Tôi đề nghị sử dụng Task<T>
thay vì Thread
; nó cho phép nhiều tham số và thực thi tốt.
Dưới đây là một ví dụ hoạt động:
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() + " ");
}
}
}
}