2010-04-08 40 views
6

Tôi đang cố gắng cập nhật một hộp văn bản. Tôi nghĩ rằng mã luồng của tôi sẽ khắc phục vấn đề, nhưng nó không. Bất cứ ai có thể giúp đỡ với điều này?Lỗi đa luồng trong C#

new Thread((ThreadStart)delegate { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); }).Start(); 

Cung cấp cho các lỗi sau:

Cross-thread operation not valid: Control 'txtCapacitance' accessed from a thread other than the thread it was created on.

Lưu ý rằng tất cả điều này đã được bắt đầu bởi một hàm dataReceived được gọi là bất cứ khi nào dữ liệu USB được nhận.

Trả lời

4

Bạn khá nên có một cái nhìn tại sử dụng BackgroundWorker Class

Có một cái nhìn tại

C# BackgroundWorker Tutorial.

+0

Điều này sẽ không khắc phục được sự cố. Nhân viên nền vẫn chạy trên một luồng khác với chuỗi giao diện người dùng. –

+0

@Marcelo Cantos, Bạn đã đọc tài liệu chưa? * Bạn phải cẩn thận không thao tác với bất kỳ đối tượng giao diện người dùng nào trong trình xử lý sự kiện DoWork của bạn. Thay vào đó, hãy liên lạc với giao diện người dùng thông qua các sự kiện ProgressChanged và RunWorkerCompleted. * –

+0

bạn nói đúng; Tôi đã sai; lời xin lỗi của tôi. Tôi nhầm lẫn điều này với một hồ bơi thread bình thường. –

6

Đối tượng giao diện người dùng chỉ có thể được gọi từ chuỗi giao diện người dùng. Điều này có thể được thực hiện thông qua phương thức Invoke của Kiểm soát:

txtCapacitance.Invoke((Action)(() => { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); })); 
+0

Tôi nhận được lỗi này: Không thể chuyển đổi biểu thức lambda thành loại 'System.Delegate' vì nó không phải là loại đại biểu – Adam

+0

Xin lỗi, bạn phải thực hiện một dàn diễn viên. Tôi đã sửa nó. –

1

Cập nhật cho bất kỳ phần tử giao diện người dùng nào phải được thực hiện trên luồng giao diện người dùng. Bạn chắc chắn có thể tính toán giá trị của bạn trên một chuỗi khác, nhưng bạn phải sử dụng phương thức kiểm soát để thực hiện cập nhật .Invoke(...).

0

thử này một

//delegate 
delegate void updateTextboxDelegate(string value); 

private void updateDisplay(string value) 
{ 
    txtCapacitance.Text = value; 
} 

//the thread 
string msg = string.empty; 
var th =new Thread(()=>{BeginInvoke(new updateTextboxDelegate(updateDisplay), msg); }); 
th.Start(); 

Hy vọng rằng sẽ làm việc cho bạn.

0

Bạn cần đảm bảo rằng bạn cập nhật textBox từ cùng một chuỗi như bạn đã tạo.

Đối với mục đích này tạo cho mình lớp helper như thế này và sử dụng phần mở rộng này thay vì sử dụng cách thông thường (đây là vài phần mở rộng tôi đã làm cho bản thân mình, nhưng một trong những thú vị bạn là changeText):

public static class ControlExtensions { 
    public static void changeStatus(this Control varControl, bool varState) { 
     if (varControl.InvokeRequired) { 
      varControl.BeginInvoke(new MethodInvoker(() => changeStatus(varControl, varState))); 
     } else { 
      varControl.Enabled = varState; 
     } 
    } 
    public static void changeText(this Control varControl, string varText) { 
     if (varControl.InvokeRequired) { 
      varControl.BeginInvoke(new MethodInvoker(() => changeText(varControl, varText))); 
     } else { 
      varControl.Text = varText; 
     } 
    } 
    public static DateTime readDateValue(this DateTimePicker varControl) { 
     if (varControl.InvokeRequired) { 
      return (DateTime) varControl.Invoke(new Func<DateTime>(() => readDateValue(varControl))); 
     } else { 
      return varControl.Value; 
     } 
    } 
    public static bool ReadStatus(this CheckBox varControl) { 
     if (varControl.InvokeRequired) { 
      return (bool) varControl.Invoke(new Func<bool>(() => ReadStatus(varControl))); 
     } 
     return varControl.Checked; 
    } 
    public static bool ReadStatus(this RadioButton varControl) { 
     if (varControl.InvokeRequired) { 
      return (bool) varControl.Invoke(new Func<bool>(() => ReadStatus(varControl))); 
     } 
     return varControl.Checked; 
    } 
    public static string readText(this Control varControl) { 
     if (varControl.InvokeRequired) { 
      return (string) varControl.Invoke(new Func<string>(() => readText(varControl))); 
     } else { 
      return varControl.Text; 
     } 
    } 
    public static bool readEnabled(this Control varControl) { 
     if (varControl.InvokeRequired) { 
      return (bool) varControl.Invoke(new Func<bool>(() => readEnabled(varControl))); 
     } else { 
      return varControl.Enabled; 
     } 
    } 

} 

Sau đó, bạn sử dụng nó như sau: txtCapacitance.changeText("new text");