2012-03-14 7 views
7

tôi có phương pháp này mà Bắt đầu một nhiệm vụ và trả về công tác cahined cuối cùng để có được kết quả:Làm cách nào tôi có thể bắt đầu một cá thể tác vụ tiếp tục?

public Task<double> GetTask() 
{ 
    return Task.Factory.StartNew((() => 10)) 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
} 

Tôi muốn có cùng một phương pháp trở về cùng một công việc nhưng không bắt đầu nó tự động với Task.Factory .Bắt đầuMới như sau:

public Task<double> GetTask2() 
{ 
    return new Task<int>((() => 10)) 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
} 

Dù sao tôi không thể tìm cách bắt đầu tác vụ được trả về bởi GetTask2 và nhận kết quả. Làm thế nào tôi có thể bắt đầu nó và nhận được kết quả?

Trả lời

1

Bạn có thể làm điều gì đó như sau. Ví dụ tôi đã tạo ba số TextBox cho mục đích minh họa.

Trước tiên hãy chọn nhiệm vụ cần thiết của bạn sử dụng một phương pháp như

public Task<double> GetTask() 
{ 
    // Return choice of task. 
    return new Task<double>(() => 10.0); 
} 

Sau đó xây dựng tiếp tục cho rằng chọn Task sử dụng một phương pháp tương tự (ommitting xử lý lỗi)

public Task<double> DefineTaskContinuation(Task<double> _task) 
{ 
    _task.ContinueWith(i => 
     { 
      textBox2.Text = (i.Result + 2).ToString(); 
      return i.Result + 2; 
     }, TaskScheduler.FromCurrentSynchronizationContext()) 
    .ContinueWith(i => 
     { 
      textBox3.Text = (i.Result + 2).ToString(); 
     }, TaskScheduler.FromCurrentSynchronizationContext()); 
    return _task; 
} 

Các nếu bạn có một hình thức với textBox1, textBox2textBox3, bạn có thể điền vào các hộp văn bản này bằng cách sử dụng đầu ra từ số đếm như sau

private void button1_Click(object sender, EventArgs e) 
{ 
    Task<double> task = DefineTaskContinuation(GetTask()); 
    task.Start(); 
    textBox1.Text = task.Result.ToString(); 
} 

Output:

The Results

Tôi hy vọng điều này sẽ giúp.

Chỉnh sửa: Do nhận xét rất đúng của @usr, câu trả lời đã được thay đổi. Lưu ý rằng TaskScheduler.FromCurrentSynchronizationContext() không phải là một yêu cầu, nhưng được sử dụng để tạo điều kiện cho đầu ra in của tôi đến luồng giao diện người dùng. Tất cả là tốt nhất.

+1

Điều này sẽ không hoạt động. Bạn cần phải bắt đầu nhiệm vụ ban đầu, ban đầu. Không phải là cuối cùng của chuỗi. – usr

+0

Tại sao? Đó không phải là câu hỏi. Chỉ cần khởi tạo tác vụ từ phương thức. Sau đó bắt đầu nó. Đơn giản. – MoonKnight

+1

Bạn đang gọi bắt đầu với nhiệm vụ tiếp tục. Bạn không thể bắt đầu nhiệm vụ tiếp tục. Nó sẽ tự động bắt đầu khi nó được hoàn thành. Bạn không thể ép buộc nó bắt đầu. – usr

2

Something như thế này:

public Task<double> GetTask() 
{ 
    var rootTask = new Task<int>((() => 10)); 
    var continuationTask = rootTask 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
    rootTask.Start(), 
    return continuationTask; 
} 

Nếu bạn muốn bắt đầu công việc chỉ sau đó, bạn có thể trả lại cả hai từ chức năng của bạn.

+0

Đây là giải pháp khả thi nhưng không phải là câu trả lời cho câu hỏi của tôi.Cảm ơn bạn anyway. – gigi

+0

Tôi đã bỏ lỡ điều gì về câu hỏi của bạn? Tại sao điều này khả thi, nhưng không phải là câu trả lời? – usr

+0

Vấn đề là tôi không muốn trả lại một tuple nhưng nhiệm vụ trả lại kết quả cuối cùng và có thể xóa nó, ví dụ như: task.Root(). Start(). Nếu bạn đọc tiêu đề câu hỏi, nó rõ ràng. – gigi

0
[TestFixture] 
public class TaskTester 
{ 
    [Test] 
    public void Test() 
    { 
     Tuple<Task<int>, Task<double>> result = GetResult(); 
     result.Item1.Start(); 
     Assert.That(result.Item2.Result, Is.EqualTo(12)); 
    } 

    private static Tuple<Task<int>, Task<double>> GetResult() 
    { 
     var task1 = new Task<int>(() => 10); 
     Task<int> task2 = task1.ContinueWith(i => i.Result + 2); 
     Task<double> task3 = task2.ContinueWith(i => (double)i.Result); 
     return new Tuple<Task<int>, Task<double>>(task1, task3); 
    } 
} 
2

Bạn có thể tạo một Task, bắt đầu phụ huynh Task, sau đó thiết lập sự tiếp nối và trả về kết quả của việc tiếp tục. Mặc dù nó có bất lợi là nó có thể chặn một luồng trong khi chờ đợi một trong đó thực sự tính toán rằng tiếp tục để hoàn thành.

public static Task<double> GetTask() 
{ 
    return new Task<double>(
     () => Task.Factory.StartNew(() => 10) 
        .ContinueWith(
         i => 
         { 
          return i.Result + 2; 
         }) 
        .ContinueWith(
         i => 
         { 
          return (double)i.Result; 
         }).Result); 
}