C #에서 매개 변수를 사용하여 스레드를 어떻게 시작합니까?
C #에서 매개 변수를 사용하여 스레드를 어떻게 시작합니까?
답변:
: :
Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
void MyParamObject(object myUrl){ //do stuff }
매개 변수 유형 이 있어야합니다object
ParameterizedThreadStart
질문 텍스트 를 사용 하고 명확하게 사용하는 방법을 알고 있다고 가정하기 때문에 그렇지 않습니다.
Thread 생성자의 오버로드 중 하나는 하나의 매개 변수를 start 메서드에 전달할 수있는 ParameterizedThreadStart 대리자를 사용합니다. 불행히도 단일 매개 변수 만 허용하고 객체로 전달하기 때문에 안전하지 않은 방식으로 수행합니다. 람다 식을 사용하여 관련 매개 변수를 캡처하고 강력한 형식으로 전달하는 것이 훨씬 쉽다는 것을 알았습니다.
다음을 시도하십시오
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))
람다 식을 사용할 수 있습니다
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;
}
매개 변수 유형은 객체 여야합니다.
편집하다:
이 답변이 올바르지는 않지만이 접근법에 반대하는 것이 좋습니다. 람다 식을 사용하면 훨씬 쉽게 읽을 수 있으며 형식 캐스팅이 필요하지 않습니다. 여기를 참조하십시오 : 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"
}
}
람다를 사용하는 간단한 방법 ..
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..
}
사용하십시오 ParametrizedThreadStart
.
이미 다양한 답변에서 언급했듯이 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
방법을. 불행히도 이와 같은 것이 존재하지 않습니다 (아직?).
그러나이 문제에 대한 제안 된 해결책 이 있습니다. 여기에는 스레드에 전달할 데이터와 작업자 메서드를 나타내는 다음과 같은 메서드가 모두 포함 된 클래스를 만드는 과정이 포함됩니다.
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() + " ");
}
}
}
}