2017-04-06 89 views
-2

當我運行下面的代碼運行良好,但並不像預期的那樣,它被假定在一個安全的線程上運行,但所有的組件都被凍結,直到它完成運行線程,它不應該在新線程上運行,以便可以使用其他控件?線程安全的C#不工作

using System; 
using System.Drawing; 
using System.Windows.Forms; 
using System.Threading; 

    public class MyFormControl : Form 
    { 
     public delegate void AddListItem(); 
     public AddListItem myDelegate; 
     private Button myButton; 
     private Thread myThread; 
     private ListBox myListBox; 
     public MyFormControl() 
     { 
     myButton = new Button(); 
     myListBox = new ListBox(); 
     myButton.Location = new Point(72, 160); 
     myButton.Size = new Size(152, 32); 
     myButton.TabIndex = 1; 
     myButton.Text = "Add items in list box"; 
     myButton.Click += new EventHandler(Button_Click); 
     myListBox.Location = new Point(48, 32); 
     myListBox.Name = "myListBox"; 
     myListBox.Size = new Size(200, 95); 
     myListBox.TabIndex = 2; 
     ClientSize = new Size(292, 273); 
     Controls.AddRange(new Control[] {myListBox,myButton}); 
     Text = " 'Control_Invoke' example"; 
     myDelegate = new AddListItem(AddListItemMethod); 
     } 
     static void Main() 
     { 
     MyFormControl myForm = new MyFormControl(); 
     myForm.ShowDialog(); 
     } 
     public void AddListItemMethod() 
     { 
     String myItem; 
     for(int i=1;i<6;i++) 
     { 
      myItem = "MyListItem" + i.ToString(); 
      myListBox.Items.Add(myItem); 
      myListBox.Update(); 
      Thread.Sleep(300); 
     } 
     } 
     private void Button_Click(object sender, EventArgs e) 
     { 
     myThread = new Thread(new ThreadStart(ThreadFunction)); 
     myThread.Start(); 
     } 
     private void ThreadFunction() 
     { 
     MyThreadClass myThreadClassObject = new MyThreadClass(this); 
     myThreadClassObject.Run(); 
     } 
    } 

// The following code assumes a 'ListBox' and a 'Button' control are added to a form, 
// containing a delegate which encapsulates a method that adds items to the listbox. 

    public class MyThreadClass 
    { 
     MyFormControl myFormControl1; 
     public MyThreadClass(MyFormControl myForm) 
     { 
     myFormControl1 = myForm; 
     } 

     public void Run() 
     { 
     // Execute the specified delegate on the thread that owns 
     // 'myFormControl1' control's underlying window handle. 
     myFormControl1.Invoke(myFormControl1.myDelegate); 
     } 
    } 
+0

看起來大部分代碼都在您在UI線程中調用的委託中。只有當你需要更新控件時,你才應該調用它,而不是爲了進行循環睡眠而進行的操作。如果你使用'async'並且使用'Task.Delay',你可以避免使用額外的線程。 – juharr

+0

你自己的評論說明了這一切:「在擁有'myFormControl1'控件的基礎窗口句柄的線程上執行指定的委託。」該線程是UI線程。 – weston

回答

2

它被假定爲一個安全的線程中運行,但所有組件都凍結 直到它完成運行的線程

當你調用上控制一些委託,該委託將運行在UI線程上。即這個代碼將在UI線程上運行:

public void AddListItemMethod() 
    { 
    String myItem; 
    for(int i=1;i<6;i++) 
    { 
     myItem = "MyListItem" + i.ToString(); 
     myListBox.Items.Add(myItem); 
     myListBox.Update(); 
     Thread.Sleep(300); // freeze UI thread 
    } 
    } 

它不應該在一個新的線程運行,因此你可以使用其他 控制?

您不能使用非UI線程的控件。

使用後臺線程的目的是一個與UI無關的長時間運行的操作。例如。你可以從磁盤讀取一些文件,查詢api,或者你可以運行一些長期運行的計算(第n個斐波那契數)。如果你將在UI線程上運行這些類型的東西,那麼你的應用程序將會凍結。因此,您應該在非UI線程上運行此類操作,並在完成長時間運行後返回到UI (儘管您可以通知用戶有關長時間運行操作的進度)。

如果要定期對UI執行某些操作,請考慮使用System.Windows.Forms.Timer組件。設置計時器的時間間隔300,並添加Tick事件處理程序:

private void Button_Click(object sender, EventArgs e) 
{ 
    timer.Start(); 
} 

private void Timer_Tick(object sender, EventArgs e) 
{ 
    myListBox.Items.Add($"MyListItem{myListBox.Items.Count + 1}"); 
} 
+0

謝謝,我會試試 –

0

的問題是Invoke運行在UI線程上的委託,所以你只需創建一個線程,只是告訴UI線程來完成所有的工作。相反,您可以使用asyncawait以及Task.Delay來簡化您的代碼。

private async void Button_Click(object sender, EventArgs e) 
{ 
    String myItem; 
    for(int i=1;i<6;i++) 
    { 
     myItem = "MyListItem" + i.ToString(); 
     myListBox.Items.Add(myItem); 
     myListBox.Update(); 
     await Task.Delay(300); 
    } 
} 

這將運行在UI上的代碼,但現在的await Task.Delay(300)不會阻塞UI線程使其能夠處理其他UI事件和停止凍結問題。

+0

謝謝,它工作得很好!,我不知道如何,但它應該像一個線程工作?我可以實例化另一個類,當點擊按鈕在背景中做一些東西,我仍然與主UI沒有問題?如果是這樣太棒了! –

+0

基本上這個代碼被編譯成一個異步狀態機器。它會在每個「await」處破壞代碼的運行,並且在300毫秒內UI線程可以自由地執行其他任務。 – juharr

+0

我明白了,所以如果{myListBox.Items.Add(myItem);}行花費大約1分鐘來完成UI,它會以任何方式凍結? –