2011-11-19 4 views
6

Tôi nhận được ngoại lệ thời gian chạy cố gắng chạy ví dụ bên dưới.TaskScheduler.FromCurrentSynchronizationContext() trong .NET

Unhandled Exception: System.InvalidOperationException: The current SynchronizationContext may not be used as a TaskScheduler. 
    at System.Threading.Tasks.SynchronizationContextTaskScheduler..ctor() 
    at System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext() 
    at TaskDemo.MyForm..ctor() in D:\myStudio\ASPNet\CSharp\CSharp4\MyApp\MyApp\Hello.cs:line 428 
    at TaskDemo.SynchronizationContextTaskScheduler() in D:\myStudio\ASPNet\CSharp\CSharp4\MyApp\MyApp\Hello.cs:line 396 
    at TaskDemo.Go() in D:\myStudio\ASPNet\CSharp\CSharp4\MyApp\CLRviaCSharp\Hello.cs:line 214 
    at ComputeOps.Main() in D:\myStudio\ASPNet\CSharp\CSharp4\MyApp\CLRviaCSharp\Hello.cs:line 23 

mẫu Mã số:

public class TaskSchedulerTest { 

    public void Test() { 
     SynchronizationContextTaskScheduler(); 
    } 

    private void SynchronizationContextTaskScheduler() { 
     var f = new MyForm(); 
     System.Windows.Forms.Application.Run(); 
    } 

    private sealed class MyForm : System.Windows.Forms.Form { 
     public MyForm() { 
      Text = "Synchronization Context Task Scheduler Demo"; 
      Visible = true; Width = 400; Height = 100; 
     } 

     private readonly TaskScheduler m_syncContextTaskScheduler = 
      TaskScheduler.FromCurrentSynchronizationContext(); 

     private CancellationTokenSource m_cts; 

     protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) { 
      if (m_cts != null) { // An operation is in flight, cancel it 
       m_cts.Cancel(); 
       m_cts = null; 
      } else {    // An operation is not in flight, start it 
       Text = "Operation running"; 
       m_cts = new CancellationTokenSource(); 

       // This task uses the default task scheduler and executes on a thread pool thread 
       var t = new Task<Int32>(() => Sum(m_cts.Token, 20000), m_cts.Token); 
       t.Start(); 

       // These tasks use the synchronization context task scheduler and execute on the GUI thread 
       t.ContinueWith(task => Text = "Result: " + task.Result, 
        CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, 
        m_syncContextTaskScheduler); 

       t.ContinueWith(task => Text = "Operation canceled", 
        CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, 
        m_syncContextTaskScheduler); 

       t.ContinueWith(task => Text = "Operation faulted", 
        CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, 
        m_syncContextTaskScheduler); 
      } 
      base.OnMouseClick(e); 
     } 
    } 
} 

Bất kỳ ý tưởng?

Trả lời

7

đặt việc tạo m_syncContextTaskScheduler vào hàm tạo biểu mẫu của bạn.

public MyForm() { 
    Text = "Synchronization Context Task Scheduler Demo"; 
    Visible = true; Width = 400; Height = 100; 
    m_syncContextTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
} 
+0

Cảm ơn! Nó hoạt động, lý do đằng sau nó là gì? – Pingpong

+3

Bởi vì 'FromCurrentSynchronizationContext()' không nằm trong ngữ cảnh hợp lệ trong quá trình khởi tạo biến (cần phải nằm trong chuỗi giao diện người dùng). Oh, và xin vui lòng chấp nhận câu trả lời, nó khuyến khích mọi người giúp bạn :) – Alex

6

Cảm ơn! Nó hoạt động, lý do đằng sau nó là gì?

Vì hàm tạo khởi tạo chỉ đọc thành viên có bộ khởi tạo quá sớm. Trình tạo lớp Form cài đặt nhà cung cấp đồng bộ hóa nếu cần thiết, một cá thể của một lớp có tên là WindowsFormsSynchronizationContext. Trình biên dịch C# tạo mã cho các khởi tạo chỉ đọc trước khi gọi hàm tạo lớp cơ sở. Di chuyển nhiệm vụ vào phần thân của hàm tạo đảm bảo rằng nó được khởi tạo sau khi gọi hàm tạo cơ sở.

Hãy cẩn thận với chỉ đọc trình khởi tạo thành viên, giữ chúng đơn giản.

+0

Cảm ơn lời giải thích. – Pingpong