आप सी # में मापदंडों के साथ एक धागा कैसे शुरू करते हैं?
आप सी # में मापदंडों के साथ एक धागा कैसे शुरू करते हैं?
जवाबों:
हां :
Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);
void MyParamObject(object myUrl){ //do stuff }
में पैरामीटर प्रकार होना चाहिएobject
ParameterizedThreadStart
प्रश्न पाठ से कैसे उपयोग करें और स्पष्ट रूप से पता है, शायद ऐसा नहीं है।
थ्रेड कंस्ट्रक्टर के 2 ओवरलोड्स में से एक 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 )
मैं पारित पैरामीटर में समस्या हो रही थी। मैंने पूर्णांक से फ़ंक्शन के लिए पूर्णांक पारित किया और इसे प्रदर्शित किया, लेकिन इसने हमेशा अलग परिणाम दिए। जैसे (1,2,2,3) (1,2,3,3) (1,1,2,3) आदि ParametrizedThreadStart प्रतिनिधि के साथ ।
इस सरल कोड ने एक आकर्षण के रूप में काम किया
Thread thread = new Thread(Work);
thread.Start(Parameter);
private void Work(object param)
{
string Parameter = (string)param;
}
ParameterizedThreadStart
एक पैरामीटर लेता है। आप एक पैरामीटर, या कई गुणों वाले एक कस्टम वर्ग भेजने के लिए उपयोग कर सकते हैं।
एक अन्य विधि उस विधि को रखना है जिसे आप एक वर्ग में उदाहरण सदस्य के रूप में शुरू करना चाहते हैं, साथ ही उन मापदंडों के गुणों के साथ जिन्हें आप सेट करना चाहते हैं। वर्ग का एक उदाहरण बनाएँ, गुण सेट करें और उदाहरण और विधि को निर्दिष्ट करते हुए थ्रेड शुरू करें, और विधि गुणों तक पहुँच सकती है।
आप एक 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() + " ");
}
}
}
}