The calling thread cannot access this object because a different thread owns it
This is a common problem with people getting started. Whenever you update your UI elements from a thread other than the main thread, you need to use:
this.Dispatcher.Invoke(() =>
{
...// your code here.
});
You can also use control.Dispatcher.CheckAccess()
to check whether the current thread owns the control. If it does own it, your code looks as normal. Otherwise, use above pattern.
The calling Thread cannot access this object because a different thread owns it. Exception
Any access to a UI element, no matter if it is read or write, must be called through main UI thread. This thread is accessible through the Dispatcher
.
In your code I see a line where this is not the case: when you are calling listBoxT2.SelectedValue
To fix the error call this code on the Dispatcher
Thread and save it to a local variable:
int selectedValue;
listBoxT2.Dispatcher.Invoke(() => selectedValue = Convert.ToInt32(listBoxT2.SelectedValue));
The rest of the code should work fine.
WPF: The calling thread cannot access this object because a different thread owns it
There are a lot of duplicates, all of which work and all of which say the same thing: You can't modify the UI from another thread. Displaying a messagebox does modify the UI. This restriction applies to all versions of Windows going back at least to Windows 95 and other OSs like Linux.
You don't need Invoke
to update the UI or raw threads to perform anything in the background either. .NET allows you to execute work in the background with Task.Run
, await its result and handle any exceptions. The only thing you need to write is :
private void SomeMethod()
{
...
}
private async void myButton_Click(object sender, RoutedEventArgs e)
{
try
{
await Task.Run(someMethod);
}
catch(Exception e)
{
ModernDialog.ShowMessage(e.ToString());
}
}
If you want to update the UI while processing in the background, eg to display progress, you can use the IProgress< T>
as explained here, to report using any type as a message, eg int, string or a full class :
private void SomeMethod(IProgress<string> progress)
{
foreach(...)
{
progress.Report("foo");
....
}
}
private async void myButton_Click(object sender, RoutedEventArgs e)
{
var progressIndicator = new Progress<string>(reportProgressMethod);
try
{
await Task.Run(()=>someMethod(progressIndicator());
}
catch(Exception e)
{
ModernDialog.ShowMessage(e.ToString());
}
}
async void
should only be used for event handlers. In all other cases, the method signature of an asynchronous method that doesn't return a result should be async Task
Solving The calling thread cannot access this object because a different thread owns it Error Without Using Dispatcher
No, you have to update the UIElement on the UI thread as the error says.
Yes, there other ways to run something on the UI thread other than using the Dispatcher
, but they like the Dispatcher
still run whatever it is you want to run on the UI thread - so will still freeze the UI.
If you are using C# 5 and .NET 4.5 or above you can easily run your long running process without blocking the UI Thread then when it completes continue on the UI thread (without worrying about how it works) using the async
and await
keywords:
private async Task<string> SimLongRunningProcessAsync()
{
await Task.Delay(2000);
return "Success";
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
button.Content = "Running...";
var result = await SimLongRunningProcessAsync();
button.Content = result;
}
If you do not have those however you will want to use the Dispatcher
. The Dispatcher
actually assists you running processes without freezing the UI
What you want to do is run the long running processes off the UI thread then when it is finished update the UI - which the Dispatcher
helps you to:
- Start long process on another thread and return immediately.
- (long process still running, UI continues to update)
- Long process finishes, update the UI on the UI thread.
e.g.:
private void UpdateButtonContent(string text)
{
button.Content = text;
}
private void SimLongRunningProcess()
{
Thread.Sleep(2000);
}
private void OnProcessFinished(Task task)
{
string content;
if(task.Exception != null)
{
content = task.Exception.Message;
}
else
{
content = "Success";
}
Dispatcher.BeginInvoke(new Action<string>(UpdateButtonContent), DispatcherPriority.Normal, content);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// Start long running process and return immediatly
var task = Task.Factory.StartNew(SimLongRunningProcess);
task.ContinueWith(OnProcessFinished);
}
The Calling thread cannot access this object because a different thread owns it - WPF
A ui elememt can only be accessed by one UI Thread. CheckBox Requires UI Thread and your timer runs on different thread. Simple code to use Dispatcher
if (client.Connected == true)
{
Dispatcher.Invoke(()=> {
// Code causing the exception or requires UI thread access
CheckBox.IsChecked =true;
});
}
OR
if (client.Connected == true)
{
Dispatcher.Invoke(new Action(()=> {
// Code causing the exception or requires UI thread access
CheckBox.IsChecked =true;
}));
}
if you receive error An object reference is required for the non-static field, method, or property
then use this
Application.Current.Dispatcher.Invoke(() =>
{
// Code causing the exception or requires UI thread access
});
C#: The calling thread cannot access this object because a different thread owns it
Try using
Application.Current.Dispatcher.Invoke
instead of
(MainWindow)System.Windows.Application.Current.MainWindow).pConnect.lbLine.Dispatcher.Invoke
The problem may be that the pConnect or lbLine is a UI object, so it, like any other UI object, cannot be used from other threads than the main thread.
Usually there is only one UI/Main thread, so all dispatchers or other ways to move execution to it will be equivalent.
The thread cannot access an object because a different thread owns it when using wpf
The other thread comes form using Task.Run
await Task.Run(() =>
{
LoadLogs(rbQueue, File.ReadAllText(filePath));
});
replace it with something like:
using (var reader = File.OpenText(filePath))
{
LoadLogs(rbQueue, await reader.ReadToEndAsync());
}
and then LoadLogs() does not need to Invoke anymore.
Related Topics
Cs0120: an Object Reference Is Required For the Nonstatic Field, Method, or Property 'Foo'
Split List into Sublists With Linq
How to Get the Application'S Path in a .Net Console Application
How to Copy the Contents of One Stream to Another
How to Find Out Which Process Is Locking a File Using .Net
In C#, Difference Between Public, Private, Protected, and Having No Access Modifier
Multiple Levels in MVC Custom Routing
Remove Duplicates from a List≪T≫ in C#
How to Cancel Task Await After a Timeout Period
Volatile Vs. Interlocked Vs. Lock
How and When to Use 'Async' and 'Await'
How to Add User-Supplied Input to an SQL Statement
How To: Execute Command Line in C#, Get Std Out Results
What Is the C# Using Block and Why Should I Use It