2011-12-20 65 views
4

我有一個長時間運行的Task,它使用回調以遞增方式提供數據(而不是最後一個ContinueWith()回調)。將任務實例傳遞給任務的代理

我希望能夠通過任務對象回來了,這回叫任務識別目的(使用Task.CurrentId)

但是,我不能工作,如何工作對象傳遞到任務委託。似乎沒有這樣做的重載,並且我不能使用閉包來完成它,因爲任務對象在那個時候沒有被定義。

例如。

public Task StartDoingSomeStuff(CallbackDelegate callback) 
{ 
    Task task = Task.Factory.StartNew(() => 
    { 
     while(whatever) 
     { 
      var results = DoSomeStuff(); 
      callback(results, task); //CS0165. How do I get hold of the task? 
     } 
    }); 

    return task; 
} 

給出:

錯誤CS0165:使用未分配的局部變量 '任務'

回答

5

拆分聲明變量並分配工作給它分成兩個語句。請確保您不使用變量任務已分配前:

public Task StartDoingSomeStuff(CallbackDelegate callback) 
{ 
    var gate = new object(); 
    lock (gate) 
    { 
     Task task = null; 
     task = Task.Factory.StartNew(() => 
     { 
      lock (gate) 
      { 
       while (whatever) 
       { 
        var results = DoSomeStuff(); 
        callback(results, task); 
       } 
      } 
     }); 
     return task; 
    } 
} 
+0

+1我只是寫同樣的事情。 :)我也會將'signal.Wait();'移到'DoSomeStuff()'後面的行來延遲鎖定。 – Groo 2011-12-20 12:04:18

+0

而不是'ManualResetEventSlim signal',最好簡單地使用'lock'語句。 @Groo評論後,我已經改變了我的回答。 – dtb 2011-12-20 12:08:45

+0

同意了,這很簡單。我仍然可能只鎖定'callback'行,但性能差異很小。 – Groo 2011-12-20 12:11:05

0

這應該工作,雖然這是不好的做法:

public Task StartDoingSomeStuff(CallbackDelegate callback) 
{ 
    Task task = null; 

    task = Task.Factory.StartNew(() => 
    { 
     while(whatever) 
     { 
      var results = DoSomeStuff(); 
      callback(results, task); //CS0165. How do I get hold of the task? 
     } 
    }); 

    return task; 
} 
+2

如果你像[dtb did](http://stackoverflow.com/a/8575136/69809)同步,那很好。這樣你就冒着競爭狀況的風險,後臺線程在分配「任務」之前完成工作。 – Groo 2011-12-20 12:06:03

1

另一種解決方案是創建一個任務鍵和字典映射鍵的任務,然後傳遞密鑰狀態到任務操作:

var taskMap = new Dictionary<object, Task>(); 
var taskKey = new object(); 
taskMap.Add(taskKey, Task.Factory.StartNew(key => { callback(results, key); }, taskKey)); 

當然你就必須從關鍵,這可能會或可能不適合您的方案中查找任務。