पृष्ठभूमि कार्यकर्ता के लिए तर्क भेजा जा रहा है?


147

मान लीजिए कि मैं एक बैकग्राउंड वर्कर को एक इंटिमेट पैरामीटर भेजना चाहता हूं, यह कैसे पूरा किया जा सकता है?

private void worker_DoWork(object sender, DoWorkEventArgs e) {

}

मुझे पता है कि यह कार्यकर्ता कब है। RunWorkerAsync (); मुझे समझ में नहीं आता कि कैसे कार्यकर्ता_डॉवर्क्स में परिभाषित किया जाए कि इसे एक अंतर पैरामीटर लेना चाहिए।

जवाबों:


235

आप इसे इस तरह शुरू करते हैं:

int value = 123;
bgw1.RunWorkerAsync(argument: value);  // the int will be boxed

और फिर

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{
   int value = (int) e.Argument;   // the 'argument' parameter resurfaces here

   ...

   // and to transport a result back to the main thread
   double result = 0.1 * value;
   e.Result = result;
}


// the Completed handler should follow this pattern 
// for Error and (optionally) Cancellation handling
private void worker_Completed(object sender, RunWorkerCompletedEventArgs e) 
{
  // check error, check cancel, then use result
  if (e.Error != null)
  {
     // handle the error
  }
  else if (e.Cancelled)
  {
     // handle cancellation
  }
  else
  {          
      double result = (double) e.Result;
      // use it on the UI thread
  }
  // general cleanup code, runs when there was an error or not.
}

38
मैं दो तर्क कैसे कर सकता हूं?
जनवरी'11

3
या मैं एक से अधिक तर्क से भरी वस्तु भेजूं?
sooprise

23
@soo: एक सहायक वर्ग या एक Tuple<A,B>(C # 4 +) का उपयोग करें (संपादित करें: हाँ, इसे सभी में पैक करने के लिए किसी ऑब्जेक्ट का उपयोग करें। उदाहरण के लिए देखें DoWorkEventArgs self)।
हेंक होल्टरमैन

लेकिन आप परिणाम के UI को कैसे सूचित करेंगे?
९'१

1
@rayray: label1.Text = e.Result.ToString();हर जगह मैंने चिह्नित किया कि जितना सुरक्षित है।
हेंक होल्टरमैन

101

हालांकि यह पहले से ही उत्तर दिया गया प्रश्न है, मैं एक और विकल्प छोड़ूंगा कि IMO पढ़ना बहुत आसान है:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (obj, e) => WorkerDoWork(value, text);
worker.RunWorkerAsync();

और हैंडलर विधि पर:

private void WorkerDoWork(int value, string text) {
    ...
}

12
मुझे नहीं पता था कि IMO का क्या मतलब है, मुझे लगा कि यह एक C # बात है। मैंने "C # IMO" को गुमराह
Electricalbah

कैसे 3 मापदंडों के बारे में?
युकीसकुर

मैं 2012 से .NET के साथ नहीं खेलता हूं, लेकिन अगर मैं गलत नहीं हूं तो आप उन मापदंडों को जोड़ सकते हैं, ... => WorkerDoWork(a, b, c);जब तक आप इसे विधि हस्ताक्षर से जोड़ सकते हैं ... WorkerDoWork(int a, string b, string c) {...
dcarneiro

1
ध्यान रखें अगर आपने इसका इस्तेमाल किया (जैसे मैंने करने की कोशिश की), आपको हर बार एक नया बैकग्राउंडर बनाना होगा (आपके उदाहरण में आप)। वरना आपके पास एक मुद्दा होगा जैसे मैंने किया। मेरे बैकग्राउंडर पिछले रन दोहराते रहेंगे। अगर एक बार चला गया तो ठीक था। 2 बार यह अंतिम रन और वर्तमान रन दोहराया। तीसरा रन अंतिम दो और वर्तमान दोहराएगा। आदि
bshea

लेकिन मान RunWorkerAsync में कैसे पास होता है?
कोडिब्यूस्टीन

47

आप इस तरह कई तर्क पारित कर सकते हैं।

List<object> arguments = new List<object>();
                    arguments.Add(argument 1);
                    arguments.Add(argument 1);
                    arguments.Add(argument n);


                    backgroundWorker2.RunWorkerAsync(arguments);

private void worker_DoWork(object sender, DoWorkEventArgs e) {

  List<object> genericlist = e.Argument as List<object>;
  extract your multiple arguments from this list and cast them and use them. 

}

@missReclusive ने "जेनेरिकलिस्ट" आइटम कास्ट किया, अर्थात, "तर्क 1" टाइप int का है तो int argument1 = (int) जेनेरिकलिस्ट [0]
Zain Ali

1
यह रखरखाव के मामले में एक बुरा विचार है। आपको सूची <ऑब्जेक्ट> पर ठोस प्रकारों का उपयोग करना चाहिए क्योंकि कम से कम आप यह पता लगाने में सक्षम होंगे कि आप क्या कर रहे थे (नीचे मेरे जवाब में एक उदाहरण देखें)
डेनिस

मैं शायद Tupleजेनेरिक ऑब्जेक्ट्स की एक सूची के बजाय एक (या एक विशेष वर्ग) पसंद करूंगा
जेम्स एस


6

की जाँच करें DoWorkEventArgs.Argument संपत्ति :

...
backgroundWorker1.RunWorkerAsync(yourInt);
...

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // Do not access the form's BackgroundWorker reference directly.
    // Instead, use the reference provided by the sender parameter.
    BackgroundWorker bw = sender as BackgroundWorker;

    // Extract the argument.
    int arg = (int)e.Argument;

    // Start the time-consuming operation.
    e.Result = TimeConsumingOperation(bw, arg);

    // If the operation was canceled by the user, 
    // set the DoWorkEventArgs.Cancel property to true.
    if (bw.CancellationPending)
    {
        e.Cancel = true;
    }
}

5

यदि आप एक से अधिक प्रकार के तर्क पास करना चाहते हैं, तो आप इसे आज़मा सकते हैं, पहले उन सभी को एक प्रकार की ऑब्जेक्ट में जोड़ सकते हैं और उस ऑब्जेक्ट को RunWorkerAsync () में पास कर सकते हैं:

   some_Method(){
   List<string> excludeList = new List<string>(); // list of strings
   string newPath ="some path";  // normal string
   Object[] args = {newPath,excludeList };
            backgroundAnalyzer.RunWorkerAsync(args);
      }

अब पृष्ठभूमि कार्यकर्ता की doWork विधि में

backgroundAnalyzer_DoWork(object sender, DoWorkEventArgs e)
      {
        backgroundAnalyzer.ReportProgress(50);
        Object[] arg = e.Argument as Object[];
        string path= (string)arg[0];
        List<string> lst = (List<string>) arg[1];
        .......
        // do something......
        //.....
       }

2
+1। इस तरीके से तर्क भेजना भी दोहराए जाने से बचने के लिए प्रत्येक रन के लिए एक नया बैकग्राउंडर शुरू करने से बचा जाता है। (कम से कम मेरे ऐप में)। इस समस्या से संबंधित मेरी टिप्पणी नीचे देखें। इसके अलावा stackoverflow.com/a/12231431/503621 और stackoverflow.com/questions/12507602/…
bshea


4

आपको हमेशा ऑब्जेक्ट प्रकारों की एक सूची के बजाय कंक्रीट प्रकार (मिश्रित डिजाइन पैटर्न का उपयोग करके) के साथ एक समग्र वस्तु का उपयोग करने की कोशिश करनी चाहिए। कौन याद करेगा कि उन वस्तुओं में से प्रत्येक क्या है? बाद में अपने कोड के रखरखाव के बारे में सोचें ... इसके बजाय, कुछ इस तरह का प्रयास करें:

Public (Class or Structure) MyPerson
                public string FirstName { get; set; }
                public string LastName { get; set; }
                public string Address { get; set; }
                public int ZipCode { get; set; }
End Class

और तब:

Dim person as new MyPerson With { .FirstName = Joe”,
                                  .LastName = "Smith”,
                                  ...
                                 }
backgroundWorker1.RunWorkerAsync(person)

और फिर:

private void backgroundWorker1_DoWork (object sender, DoWorkEventArgs e)
{
        MyPerson person = e.Argument as MyPerson
        string firstname = person.FirstName;
        string lastname = person.LastName;
        int zipcode = person.ZipCode;                                 
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.