पैरामीटर के साथ थ्रेडस्टार्ट


261

आप सी # में मापदंडों के साथ एक धागा कैसे शुरू करते हैं?


इस प्रश्न का उत्तर रनटाइम के सभी संस्करणों में व्यापक रूप से भिन्न है - क्या 3.5 उत्तर ठीक है?
क्विलब्रेकर

4
वाह। मैं आपके कुछ पुराने प्रश्नों का संपादन कर रहा हूं, लेकिन यह पूर्णकालिक नौकरी हो सकती है। मैं भूल गया था, उह, आपने वर्षों में कितना सुधार किया है। :-)
जॉन सौन्डर्स 19

अगर मैंने ऐसा संक्षिप्त प्रश्न पूछा तो मुझे 5 नकारात्मक अंक या और भी अधिक मिलेंगे! हालांकि सवाल और जवाब ने मेरी मदद की।
मोहम्मद मुसावी

जवाबों:


174

हां :

Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);

14
यह वही है: थ्रेडस्टार्ट प्रोसेसटैस्क्रेड = डेलीगेट {प्रोसेसटैक्सेस (डेटाबॉक्स.डाटाबॉक्सिड); }; नया थ्रेड (processTaskThread) .Start ();
जेएल

43
MyParamObject और myUrl क्या है?
डायलेक्स

3
इस मामले void MyParamObject(object myUrl){ //do stuff }में पैरामीटर प्रकार होना चाहिएobject
एल्शान

15
-1 क्योंकि उत्तर मानता है कि ओपी जानता है कि ParameterizedThreadStartप्रश्न पाठ से कैसे उपयोग करें और स्पष्ट रूप से पता है, शायद ऐसा नहीं है।
ज्येल्टन

2
मेरे पास यह त्रुटि है CS0123 'अपडेटडीबी' के लिए कोई अधिभार नहीं है, 'पैरामीटरीट्रेडरस्टार्ट' प्रतिनिधि से मेल खाता है
ओमिड फ़ारविड

482

थ्रेड कंस्ट्रक्टर के 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) {
  ...
}

41
+1: भले ही वर्तमान में चयनित उत्तर बिल्कुल सही है, लेकिन JaredPar द्वारा यह एक बेहतर है। यह बस सबसे व्यावहारिक मामलों के लिए सबसे अच्छा समाधान है।
गलकटोर

2
यह समाधान तब बेहतर है जब स्टैंडरार्ड ParameterizedThreadStart
Piotr Owsiak

5
बहुत अच्छा लगा। "न्यू थ्रेड () => FooBar ()) .Start ();
थॉमस जेस्पर्सन

12
बहुत बढ़िया, यह VB.NET लोगों के लिए हैDim thr As New Thread(Sub() DoStuff(settings))
डॉ। दुष्ट

3
@bavaza मैं सिर्फ स्थिर प्रकार की जाँच करने के लिए बात कर रहे थे
JaredPar

141

आप लैम्बडा एक्सप्रेशन का उपयोग कर सकते हैं

private void MyMethod(string param1,int param2)
{
  //do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();

यह अब तक का सबसे अच्छा जवाब है जो मुझे मिल सकता है, यह तेज और आसान है।


6
सरल मामलों के लिए सबसे अच्छा समाधान IMO
Dunc

1
वह क्या है => और मुझे सिंटैक्स के बारे में अधिक जानकारी कहां मिल सकती है?
निक

2
यह एक लंबोदर अभिव्यक्ति है, इन पतों पर कुछ जानकारी मिल सकती है: msdn.microsoft.com/en-us/library/vstudio/bb397687.aspx | codeproject.com/Articles/24255/Exploring-Lambda-Expression-in-C | dotnetperls.com/lambda
जॉर्जी-

1
इसने मेरे लिए काम किया। मैंने ParameterizedThreadStart और इसके विभिन्न रूपों की कोशिश की, लेकिन कोई खुशी नहीं हुई। मैं एक कथित रूप से सरल कंसोल एप्लिकेशन में .NET फ्रेमवर्क 4 का उपयोग कर रहा था।
डैनियल हॉलिनरेके

यह उन लोगों के लिए सबसे अच्छा काम करता है जो इस तरह के प्रतिनिधियों के लिए उपयोग किए जाते हैं। शुरुआती लोगों के लिए udnerstand के लिए मुश्किल हो सकता है। यह हालांकि C # मानकों के लिए साफ है। स्वीकृत उत्तर मेरे लिए काम नहीं करता है और मेरे पास यह जानने का समय नहीं है कि क्यों।
बिटरब्लू

37
Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param)
{
    string Parameter = (string)param;
}

पैरामीटर प्रकार एक ऑब्जेक्ट होना चाहिए।

संपादित करें:

हालांकि यह जवाब गलत नहीं है, मैं इस दृष्टिकोण के खिलाफ सिफारिश करता हूं। लैम्ब्डा अभिव्यक्ति का उपयोग करना बहुत आसान है और टाइप कास्टिंग की आवश्यकता नहीं है। यहां देखें: https://stackoverflow.com/a/1195915/52551


आप एक कोड के साथ मदद क्यों कर रहे हैं जो संकलन नहीं करता Parameter? )
सेबेस्टियन ज़ेवरी वाईनोनीकी

32
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"
    }
}

3
यह मुझे "
DoWork

1
यदि आप थ्रेड टी आरंभीकरण में थ्रेडमेथोड को पास कर देते हैं तो क्या अंतर होगा?
जो

याद रखें, पैरामीटर प्रकार 'ऑब्जेक्ट' प्रकार का है
कुणाल उप्पल

28

सरल तरीका जैसे लंबोदर का उपयोग करना ।।

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..
}



6

जैसा कि पहले ही विभिन्न उत्तरों में उल्लेख किया जा चुका है, 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();

तो इस तरह से आप बस कास्टिंग करने से बचते हैं और एक थ्रेड को डेटा प्रदान करने का एक प्रकार है; ;;;


वाह, टिप्पणी के बिना एक अपमान ... या तो मेरा जवाब उतना ही बुरा है जितना कि कलाकारों या पाठक को समझ में नहीं आया कि मैंने यहां क्या इशारा करने की कोशिश की? ;-)
मार्कस सफ़र

1
मुझे आपका समाधान बहुत ज्ञानवर्धक लगा, बधाई। बस जोड़ना चाहता था कि मैंने पहले ही नेट में परीक्षण किया है। निम्नलिखित पर ध्यान दें और बिना खोजबीन के काम किया! :-) private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
पॉल एफफोर्ड

@PaulEfford धन्यवाद ;-) आपका समाधान बहुत अच्छा लगता है। लेकिन आपको विशिष्ट जानकारी टाइप करने की सुविधा नहीं मिलती है क्योंकि यह अभी भी किसी वस्तु, बॉक्स के लिए सही होगा? (जैसे message.Lengthसंभव नहीं है और इतने पर)
मार्कस सफर

1
सही ... आप message.GetType () और कास्ट कर सकते हैं यदि किसी विशिष्ट संपत्ति की तरह की आवश्यकता हो 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 )
पॉल एफफोर्ड

5

मैं पारित पैरामीटर में समस्या हो रही थी। मैंने पूर्णांक से फ़ंक्शन के लिए पूर्णांक पारित किया और इसे प्रदर्शित किया, लेकिन इसने हमेशा अलग परिणाम दिए। जैसे (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; 
}

4

ParameterizedThreadStartएक पैरामीटर लेता है। आप एक पैरामीटर, या कई गुणों वाले एक कस्टम वर्ग भेजने के लिए उपयोग कर सकते हैं।

एक अन्य विधि उस विधि को रखना है जिसे आप एक वर्ग में उदाहरण सदस्य के रूप में शुरू करना चाहते हैं, साथ ही उन मापदंडों के गुणों के साथ जिन्हें आप सेट करना चाहते हैं। वर्ग का एक उदाहरण बनाएँ, गुण सेट करें और उदाहरण और विधि को निर्दिष्ट करते हुए थ्रेड शुरू करें, और विधि गुणों तक पहुँच सकती है।




1
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`
    }
}

0

मैं 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;
        }
    }

-2
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() + " ");
            }
        }
    }
}

C # थ्रेड्स के साथ मल्टी थ्रेडिंग आपको साझा मेमोरी के माध्यम से सिंक्रनाइज़ करने वाले अधिक कुशल एप्लिकेशन विकसित करने की अनुमति देता है।
मोहम्मद हसन इस्माइल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.