爲了解釋這個問題,我把所有需要的東西放到一個小樣本應用程序中,希望能夠解釋這個問題。我真的試圖儘可能減少所有行數,但在我的實際應用中,這些不同的演員彼此不認識,也不應該這樣做。所以,簡單的答案就像「將上面的幾行變量並調用Invoke」不起作用。BindingSource和跨線程異常
所以讓我們從代碼開始,然後再解釋一點。起初有一個簡單的類實現INotifyPropertyChanged:
public class MyData : INotifyPropertyChanged
{
private string _MyText;
public MyData()
{
_MyText = "Initial";
}
public string MyText
{
get { return _MyText; }
set
{
_MyText = value;
PropertyChanged(this, new PropertyChangedEventArgs("MyText"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
所以沒什麼特別的。這裏的示例代碼,可以簡單地放入任何空的控制檯應用程序項目:
static void Main(string[] args)
{
// Initialize the data and bindingSource
var myData = new MyData();
var bindingSource = new BindingSource();
bindingSource.DataSource = myData;
// Initialize the form and the controls of it ...
var form = new Form();
// ... the TextBox including data bind to it
var textBox = new TextBox();
textBox.DataBindings.Add("Text", bindingSource, "MyText");
textBox.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
textBox.Dock = DockStyle.Top;
form.Controls.Add(textBox);
// ... the button and what happens on a click
var button = new Button();
button.Text = "Click me";
button.Dock = DockStyle.Top;
form.Controls.Add(button);
button.Click += (_, __) =>
{
// Create another thread that does something with the data object
var worker = new BackgroundWorker();
worker.RunWorkerCompleted += (___, ____) => button.Enabled = true;
worker.DoWork += (___, _____) =>
{
for (int i = 0; i < 10; i++)
{
// This leads to a cross-thread exception
// but all i'm doing is simply act on a property in
// my data and i can't see here that any gui is involved.
myData.MyText = "Try " + i;
}
};
button.Enabled = false;
worker.RunWorkerAsync();
};
form.ShowDialog();
}
,如果您運行這段代碼,你會試圖改變MyText
財產得到一個跨線程異常。這將導致MyData
對象調用PropertyChanged
,這將被BindindSource
捕獲。然後,根據Binding
,嘗試更新TextBox
的Text
屬性。這顯然導致了例外。這裏
我最大的問題來自於一個事實,即MyData
對象不應該知道的GUI任何東西(因爲它是一個簡單的數據對象)。工作者線程也不知道關於gui的任何信息。它只是作用於一堆數據對象並操縱它們。
恕我直言,我認爲BindingSource
應該檢查接收對象生活在哪個線程,並做適當的Invoke()
來獲得它們的值。不幸的是,這不是內置的(或者我錯了嗎?),所以我的問題是:
如何解決這個跨線程異常如果數據對象或工作線程知道任何關於正在監聽的綁定源因爲他們的事件將數據推送到gui中。
但問題是,我不知道'MyData'類中的UI線程。那麼如何調用UI線程,如果我沒有訪問任何當前在窗體上調用'Invoke()'的控件? – Oliver
@Oliver:嘿,你解決了這個問題?我也堅持這樣的事情? –
@mahesh:爲這個問題添加一個自己的答案,我如何解決這個問題。這並不完美,但總比沒有好。 – Oliver