To keep my question simple lets says that I use a thread to update on the fly a replacement in a string. In my real code I need a thread. I know I can avoid it in this simple example.
So, my software has two fields. The user select a file, write a (sort of) regex and see the result of the modification at the same time he types his sentence. I start the thread when the user select a file (see listViewFiles_SelectionChanged method). The work of my thread is in DoWork method.
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();
}
When my thread do his work I get an exception on the line string searchRegEx = GenerateRegex(_searchTextBox.Text); : The calling thread cannot access this object because a different thread owns it. I read a lot about this exception but I don't understand it.
To fix it I surround my code with a Dispatcher. I don't understand the mecanism but it works. I have no idea if it is correct or performant but it works.
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();
}
I would like to know if this code is correct and prfomant. You see the foreach instruction in comment. My code should do a lot of work and I don't know if doing this in a delagate is the best way do do this. Utility and good practice of the Dispatcher ?