2013-02-27 11 views
6

के साथ पृष्ठभूमि कार्यकर्ता बनाना मुझे कतार बनाने और पृष्ठभूमिवर्कर के साथ इसका उपयोग करने की आवश्यकता है। तो मैं संचालन जोड़ सकता हूं और जब कोई आगे किया जाता है तो पृष्ठभूमि में शुरू होता है। मुझे यह कोड Google द्वारा मिला:कतार

public class QueuedBackgroundWorker<T> 
{ 
    public void QueueWorkItem(
     Queue queue, 
     T inputArgument, 
     Func<T> doWork, 
     Action workerCompleted) 
    { 
     if (queue == null) throw new ArgumentNullException("queue"); 

     BackgroundWorker bw = new BackgroundWorker(); 
     bw.WorkerReportsProgress = false; 
     bw.WorkerSupportsCancellation = false; 
     bw.DoWork += (sender, args) => 
     { 
      if (doWork != null) 
      { 
       args.Result = doWork(new DoWorkArgument<T>((T)args.Argument)); 
      } 
     }; 
     bw.RunWorkerCompleted += (sender, args) => 
     { 
      if (workerCompleted != null) 
      { 
       workerCompleted(new WorkerResult<T>((T)args.Result, args.Error)); 
      } 
      queue.Dequeue(); 
      if (queue.Count > 0) 
      { 
       QueueItem<T> nextItem = queue.Peek() as QueueItem<T>; 
       nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument); 
      } 
     }; 

     queue.Enqueue(new QueueItem<T>(bw, inputArgument)); 
     if (queue.Count == 1) 
     { 
      QueueItem<T> nextItem = queue.Peek() as QueueItem<T>; 
      nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument); 
     } 
    } 
} 

public class DoWorkArgument<T> 
{ 
    public DoWorkArgument(T argument) 
    { 
     this.Argument = argument; 
    } 
    public T Argument { get; private set; } 
} 

public class WorkerResult<T> 
{ 
    public WorkerResult(T result, Exception error) 
    { 
     this.Result = result; 
     this.Error = error; 
    } 

    public T Result { get; private set; } 
    public Exception Error { get; private set; } 
} 

public class QueueItem<T> 
{ 
    public QueueItem(BackgroundWorker backgroundWorker, T argument) 
    { 
     this.BackgroundWorker = backgroundWorker; 
     this.Argument = argument; 
    } 

    public T Argument { get; private set; } 
    public BackgroundWorker BackgroundWorker { get; private set; } 
} 

लेकिन मुझे doWork और Worker के साथ समस्या है। मुझे त्रुटि मिलती है:

Delegate 'Func' does not take 1 arguments

मैं इसे कैसे ठीक कर सकता हूं? मुझे पैरामीटर कैसे बदलना चाहिए?

public class BackgroundQueue 
{ 
    private Task previousTask = Task.FromResult(true); 
    private object key = new object(); 
    public Task QueueTask(Action action) 
    { 
     lock (key) 
     { 
      previousTask = previousTask.ContinueWith(t => action() 
       , CancellationToken.None 
       , TaskContinuationOptions.None 
       , TaskScheduler.Default); 
      return previousTask; 
     } 
    } 

    public Task<T> QueueTask<T>(Func<T> work) 
    { 
     lock (key) 
     { 
      var task = previousTask.ContinueWith(t => work() 
       , CancellationToken.None 
       , TaskContinuationOptions.None 
       , TaskScheduler.Default); 
      previousTask = task; 
      return task; 
     } 
    } 
} 

पिछले आप यह सुनिश्चित करें कि केवल एक समय में एक पर काम किया है की एक निरंतरता के रूप में प्रत्येक नए कार्रवाई को जोड़ कर, अगले आइटम के रूप में: धन्यवाद

+1

कम से कम जो लाइन पर संकेत मिलता है। और शायद उस पंक्ति को पोस्ट करें। टीएल; डीआर –

उत्तर

20

यहाँ एक बहुत छोटे विधि करता है कि तुम क्या चाहते हो पिछली वस्तु समाप्त होने तक शुरू नहीं होगी, आप सुनिश्चित करते हैं कि काम करने के लिए कुछ भी नहीं होने पर निष्क्रिय होने के आसपास कोई धागा नहीं है, और आप सुनिश्चित करते हैं कि वे सभी क्रम में किए गए हैं।

यह भी ध्यान रखें कि अगर आपको कभी लगता है कि आपको एक कतार की आवश्यकता होगी, और कोई संख्या नहीं है, तो आप सभी सदस्यों को static बना सकते हैं, लेकिन यह आपके ऊपर है।

+0

बेहतर दिखता है, इसके लिए धन्यवाद। अब मैं इसका उपयोग इस तरह कर रहा हूं: 'bgQueue.QueueTask (() => CreateConvertingProccess (item.FullName));'। क्या आप मेरी मदद कर सकते हैं जब एक कार्य पूरा हो जाता है तो मैं विधि कैसे कॉल कर सकता हूं? क्या मुझे इसे लॉक के बाद जोड़ा जाना चाहिए? मेरा मतलब है कि जब मैं विधि जोड़ना चाहता हूं जिसे मैं RunWorker में जोड़ दूंगा। –

+0

बहुत बहुत धन्यवाद, यह काम कर रहा है। मुझे कार्य के साथ काम करने के बारे में सीखना चाहिए। –

+0

क्या आप कृपया एक बार मेरी मदद कर सकते हैं। अगर कतार खाली है तो मैं कैसे पता लगा सकता हूं? –

0

ऐसा लगता है कि आप दूसरा सामान्य पैरामीटर खो रहे हैं - टाउट;

निम्नलिखित कोड यह का ध्यान रखना चाहिए:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 

public static class QueuedBackgroundWorker 
{ 
    public static void QueueWorkItem<Tin, Tout>(
     Queue<QueueItem<Tin>> queue, 
     Tin inputArgument, 
     Func<DoWorkArgument<Tin>, Tout> doWork, 
     Action<WorkerResult<Tout>> workerCompleted) 
    { 
     if (queue == null) throw new ArgumentNullException("queue"); 

     BackgroundWorker bw = new BackgroundWorker(); 
     bw.WorkerReportsProgress = false; 
     bw.WorkerSupportsCancellation = false; 
     bw.DoWork += (sender, args) => 
      { 
       if (doWork != null) 
       { 
        args.Result = doWork(new DoWorkArgument<Tin>((Tin)args.Argument)); 
       } 
      }; 
     bw.RunWorkerCompleted += (sender, args) => 
      { 
       if (workerCompleted != null) 
       { 
        workerCompleted(new WorkerResult<Tout>((Tout)args.Result, args.Error)); 
       } 
       queue.Dequeue(); 
       if (queue.Count > 0) 
       { 
        QueueItem<Tin> nextItem = queue.Peek(); // as QueueItem<T>; 
        nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument); 
       } 
      }; 

     queue.Enqueue(new QueueItem<Tin>(bw, inputArgument)); 
     if (queue.Count == 1) 
     { 
      QueueItem<Tin> nextItem = queue.Peek() as QueueItem<Tin>; 
      nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument); 
     } 
    } 
} 

public class DoWorkArgument<T> 
{ 
    public DoWorkArgument(T argument) 
    { 
     this.Argument = argument; 
    } 

    public T Argument { get; private set; } 
} 

public class WorkerResult<T> 
{ 
    public WorkerResult(T result, Exception error) 
    { 
     this.Result = result; 
     this.Error = error; 
    } 

    public T Result { get; private set; } 

    public Exception Error { get; private set; } 
} 

public class QueueItem<T> 
{ 
    public QueueItem(BackgroundWorker backgroundWorker, T argument) 
    { 
     this.BackgroundWorker = backgroundWorker; 
     this.Argument = argument; 
    } 

    public T Argument { get; private set; } 

    public BackgroundWorker BackgroundWorker { get; private set; } 
} 

और उपयोग किया जाना चाहिए:

private readonly Queue<QueueItem<int>> _workerQueue = new Queue<QueueItem<int>>(); 
    private int _workerId = 1; 

    [Test] 
    public void BackgroundTest() 
    { 
     QueuedBackgroundWorker.QueueWorkItem(
      this._workerQueue, 
      this._workerId++, 
      args => // DoWork 
       { 
        var currentTaskId = args.Argument; 
        var now = DateTime.Now.ToLongTimeString(); 
        var message = string.Format("DoWork thread started at '{0}': Task Number={1}", now, currentTaskId); 
        return new { WorkerId = currentTaskId, Message = message }; 
       }, 
      args => // RunWorkerCompleted 
       { 
        var currentWorkerId = args.Result.WorkerId; 
        var msg = args.Result.Message; 

        var now = DateTime.Now.ToShortTimeString(); 
        var completeMessage = string.Format(
         "RunWorkerCompleted completed at '{0}'; for Task Number={1}, DoWork Message={2}", 
         now, 
         currentWorkerId, 
         msg); 
       } 
      ); 
    }