【发布时间】:2012-05-18 14:20:08
【问题描述】:
为了让我的问题简单,让我们说我使用一个线程来动态更新字符串中的替换。在我的真实代码中,我需要一个线程。我知道我可以在这个简单的例子中避免它。
所以,我的软件有两个字段。用户选择一个文件,编写一个(某种)正则表达式并在输入句子的同时查看修改结果。我在用户选择文件时启动线程(请参阅 listViewFiles_SelectionChanged 方法)。我的线程的工作是在 DoWork 方法中。
public void DoWork()
{
while (true)
{
FileData fileData = _selectedFile;
if (fileData != null)
{
string name = fileData.FileName;
string searchRegEx = GenerateRegex(_searchTextBox.Text);
string replacement = _replaceTextBox.Text;
name = Regex.Replace(name, searchRegEx, replacement);
/*
foreach (var action in _actionCollection)
{
name = action.Rename(name);
}*/
_searchSample.Content = fileData.FileName;
_replaceSample.Content = name;
}
Thread.Sleep(1000);
}
}
private void listViewFiles_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
_selectedFile = listViewFiles.SelectedItem as FileData;
_thread.Start();
}
当我的线程执行他的工作时,我在行字符串 searchRegEx = GenerateRegex(_searchTextBox.Text); 上遇到异常。 :调用线程无法访问此对象,因为不同的线程拥有它。我读了很多关于这个异常的内容,但我不明白。
为了解决这个问题,我用 Dispatcher 包围了我的代码。我不明白机制,但它的工作原理。我不知道它是否正确或高效,但它有效。
public void DoWork()
{
while (true)
{
FileData fileData = _selectedFile;
if (fileData != null)
{
//use Window.Dispatcher
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(delegate()
{
string name = fileData.FileName;
string searchRegEx = GenerateRegex(_searchTextBox.Text);
string replacement = _replaceTextBox.Text;
name = Regex.Replace(name, searchRegEx, replacement);
/*
foreach (var action in _actionCollection)
{
name = action.Rename(name);
}*/
_searchSample.Content = fileData.FileName;
_replaceSample.Content = name;
}));
}
Thread.Sleep(1000);
}
}
private void listViewFiles_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
_selectedFile = listViewFiles.SelectedItem as FileData;
_thread.Start();
}
我想知道这段代码是否正确和正确。您会在评论中看到 foreach 指令。我的代码应该做很多工作,我不知道在 delagate 中这样做是否是最好的方法。 Dispatcher 的实用性和良好实践?
【问题讨论】:
-
为什么你根本不使用 mvvm ? Dispatcher.Invoke 只是在 UI 线程中同步调用委托,因此此代码可能会导致 ui 冻结。由于尝试在不同的线程中访问 _searchTextBox 元素而出现错误,因此您只需将 ui 更新和代码分开即可。
-
@trimeyko 因为我对 MVVM 不太满意。但你说得对,我应该使用它。
-
您是否考虑过使用 BlockingQueue 作为快速修复?从 UI 推送 _replaceTextBox.Text 并在另一个线程中执行工作。
-
@trimeyko,我不明白为什么 MVVM 会解决这个问题。顺便说一句,绑定更难线程化,因为您很难诊断问题。
标签: c# .net multithreading