C# WPF - Accessing objects created on the UI thread from worker thread without blocking
I’m working on a plugin WPF application, which is instantiated from a larger application and regularly interfaces with the API of the main application. The problem I have is that my plugin UI is blocked whenever an intensive operation takes place interfacing with the main application.
In an attempt to resolve this I execute a task, and use the SynchronizationContext of the UI to call the operation which accesses the main application.
For test purposes I have simple WPF application MainWindow and set the ViewContext of the view model as follows
((MainWindowViewModel)DataContext).ViewContext = SynchronizationContext.Current;
Then within my view model I perform the intensive operation from a task as follows.
public void BeginTaskWork()
Task.Factory.StartNew(() =>
ViewContext.Post(new SendOrPostCallback((o) =>
PerformIntensiveOperation();
), null);
This overcomes the obstacle of calling objects on the UI thread from a task but does not prevent the UI from hanging.
I suppose this is to be expected because I am still executing an intensive task on the UI thread.
So, basically I am asking if there is something I can do to prevent the UI from being blocked when I try to perform operations that interface with the parent application.
Update:
To clarify, the intensive operation involves accessing the API to the parent application and this is owned by the UI thread.
Also, when I simply attempt to perform this on another thread or task I get the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it." This is the reason I tried to the combination of a task and Synchronization context.
Thanks.
c# wpf multithreading
add a comment |
I’m working on a plugin WPF application, which is instantiated from a larger application and regularly interfaces with the API of the main application. The problem I have is that my plugin UI is blocked whenever an intensive operation takes place interfacing with the main application.
In an attempt to resolve this I execute a task, and use the SynchronizationContext of the UI to call the operation which accesses the main application.
For test purposes I have simple WPF application MainWindow and set the ViewContext of the view model as follows
((MainWindowViewModel)DataContext).ViewContext = SynchronizationContext.Current;
Then within my view model I perform the intensive operation from a task as follows.
public void BeginTaskWork()
Task.Factory.StartNew(() =>
ViewContext.Post(new SendOrPostCallback((o) =>
PerformIntensiveOperation();
), null);
This overcomes the obstacle of calling objects on the UI thread from a task but does not prevent the UI from hanging.
I suppose this is to be expected because I am still executing an intensive task on the UI thread.
So, basically I am asking if there is something I can do to prevent the UI from being blocked when I try to perform operations that interface with the parent application.
Update:
To clarify, the intensive operation involves accessing the API to the parent application and this is owned by the UI thread.
Also, when I simply attempt to perform this on another thread or task I get the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it." This is the reason I tried to the combination of a task and Synchronization context.
Thanks.
c# wpf multithreading
What you are doing right now is creating a task on a threadpool thread that schedules work on UI thread so obviously this will block. It's the same as just callingPerformIntensiveOperation()
– FCin
Nov 12 '18 at 12:25
You may not be able to, if interfacing with the larger app demands you do so from the UI thread. Try to run your intensive operation from a regular task, and only update your UI from the synchronization context.
– Nick
Nov 12 '18 at 12:25
Thanks. I can't run the operation from a task, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it."
– user5265160
Nov 12 '18 at 14:03
add a comment |
I’m working on a plugin WPF application, which is instantiated from a larger application and regularly interfaces with the API of the main application. The problem I have is that my plugin UI is blocked whenever an intensive operation takes place interfacing with the main application.
In an attempt to resolve this I execute a task, and use the SynchronizationContext of the UI to call the operation which accesses the main application.
For test purposes I have simple WPF application MainWindow and set the ViewContext of the view model as follows
((MainWindowViewModel)DataContext).ViewContext = SynchronizationContext.Current;
Then within my view model I perform the intensive operation from a task as follows.
public void BeginTaskWork()
Task.Factory.StartNew(() =>
ViewContext.Post(new SendOrPostCallback((o) =>
PerformIntensiveOperation();
), null);
This overcomes the obstacle of calling objects on the UI thread from a task but does not prevent the UI from hanging.
I suppose this is to be expected because I am still executing an intensive task on the UI thread.
So, basically I am asking if there is something I can do to prevent the UI from being blocked when I try to perform operations that interface with the parent application.
Update:
To clarify, the intensive operation involves accessing the API to the parent application and this is owned by the UI thread.
Also, when I simply attempt to perform this on another thread or task I get the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it." This is the reason I tried to the combination of a task and Synchronization context.
Thanks.
c# wpf multithreading
I’m working on a plugin WPF application, which is instantiated from a larger application and regularly interfaces with the API of the main application. The problem I have is that my plugin UI is blocked whenever an intensive operation takes place interfacing with the main application.
In an attempt to resolve this I execute a task, and use the SynchronizationContext of the UI to call the operation which accesses the main application.
For test purposes I have simple WPF application MainWindow and set the ViewContext of the view model as follows
((MainWindowViewModel)DataContext).ViewContext = SynchronizationContext.Current;
Then within my view model I perform the intensive operation from a task as follows.
public void BeginTaskWork()
Task.Factory.StartNew(() =>
ViewContext.Post(new SendOrPostCallback((o) =>
PerformIntensiveOperation();
), null);
This overcomes the obstacle of calling objects on the UI thread from a task but does not prevent the UI from hanging.
I suppose this is to be expected because I am still executing an intensive task on the UI thread.
So, basically I am asking if there is something I can do to prevent the UI from being blocked when I try to perform operations that interface with the parent application.
Update:
To clarify, the intensive operation involves accessing the API to the parent application and this is owned by the UI thread.
Also, when I simply attempt to perform this on another thread or task I get the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it." This is the reason I tried to the combination of a task and Synchronization context.
Thanks.
c# wpf multithreading
c# wpf multithreading
edited Nov 12 '18 at 14:14
user5265160
asked Nov 12 '18 at 12:21
user5265160user5265160
86
86
What you are doing right now is creating a task on a threadpool thread that schedules work on UI thread so obviously this will block. It's the same as just callingPerformIntensiveOperation()
– FCin
Nov 12 '18 at 12:25
You may not be able to, if interfacing with the larger app demands you do so from the UI thread. Try to run your intensive operation from a regular task, and only update your UI from the synchronization context.
– Nick
Nov 12 '18 at 12:25
Thanks. I can't run the operation from a task, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it."
– user5265160
Nov 12 '18 at 14:03
add a comment |
What you are doing right now is creating a task on a threadpool thread that schedules work on UI thread so obviously this will block. It's the same as just callingPerformIntensiveOperation()
– FCin
Nov 12 '18 at 12:25
You may not be able to, if interfacing with the larger app demands you do so from the UI thread. Try to run your intensive operation from a regular task, and only update your UI from the synchronization context.
– Nick
Nov 12 '18 at 12:25
Thanks. I can't run the operation from a task, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it."
– user5265160
Nov 12 '18 at 14:03
What you are doing right now is creating a task on a threadpool thread that schedules work on UI thread so obviously this will block. It's the same as just calling
PerformIntensiveOperation()
– FCin
Nov 12 '18 at 12:25
What you are doing right now is creating a task on a threadpool thread that schedules work on UI thread so obviously this will block. It's the same as just calling
PerformIntensiveOperation()
– FCin
Nov 12 '18 at 12:25
You may not be able to, if interfacing with the larger app demands you do so from the UI thread. Try to run your intensive operation from a regular task, and only update your UI from the synchronization context.
– Nick
Nov 12 '18 at 12:25
You may not be able to, if interfacing with the larger app demands you do so from the UI thread. Try to run your intensive operation from a regular task, and only update your UI from the synchronization context.
– Nick
Nov 12 '18 at 12:25
Thanks. I can't run the operation from a task, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it."
– user5265160
Nov 12 '18 at 14:03
Thanks. I can't run the operation from a task, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it."
– user5265160
Nov 12 '18 at 14:03
add a comment |
1 Answer
1
active
oldest
votes
Perform your intensive operation in another thread. This will not block the UI. If you need to call objects on UI thread from another thread than do exactly that - call them on UI thread. You can do this by doing an Invoke on current dispatcher.
await Application.Current.Dispatcher.BeginInvoke(() => SetPropertyOnUIThread());
Thanks for the suggestion. I can't run the operation on another thread, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.". The intensive operation involves accesses to the main application API, which is owned by the UI thread. The application is a plugin.
– user5265160
Nov 12 '18 at 14:05
Have you tried this? I am saying this because it seems like this solves the issue. You are getting this error because you are trying to update something between threads. This usually solves the problem. So for instance, if you have a view model that has a property that is binded to a progress level than changing this property from different thread will yield this error since the progress bar is owned by UI thread, BUT, if you call this property change on UI thread than it is okay.
– Rob
Nov 12 '18 at 14:11
I tried : await Application.Current.Dispatcher.BeginInvoke(new Action(() => PerformIntensiveOperation()));, however this still seems to block.
– user5265160
Nov 12 '18 at 15:06
When I run the WPF application on a separate thread, the above dispatcher invoke call works well and frees up the UI. This is a good solution to my problem because the application thread has direct access to the parent API.
– user5265160
Nov 12 '18 at 17:30
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262104%2fc-sharp-wpf-accessing-objects-created-on-the-ui-thread-from-worker-thread-with%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Perform your intensive operation in another thread. This will not block the UI. If you need to call objects on UI thread from another thread than do exactly that - call them on UI thread. You can do this by doing an Invoke on current dispatcher.
await Application.Current.Dispatcher.BeginInvoke(() => SetPropertyOnUIThread());
Thanks for the suggestion. I can't run the operation on another thread, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.". The intensive operation involves accesses to the main application API, which is owned by the UI thread. The application is a plugin.
– user5265160
Nov 12 '18 at 14:05
Have you tried this? I am saying this because it seems like this solves the issue. You are getting this error because you are trying to update something between threads. This usually solves the problem. So for instance, if you have a view model that has a property that is binded to a progress level than changing this property from different thread will yield this error since the progress bar is owned by UI thread, BUT, if you call this property change on UI thread than it is okay.
– Rob
Nov 12 '18 at 14:11
I tried : await Application.Current.Dispatcher.BeginInvoke(new Action(() => PerformIntensiveOperation()));, however this still seems to block.
– user5265160
Nov 12 '18 at 15:06
When I run the WPF application on a separate thread, the above dispatcher invoke call works well and frees up the UI. This is a good solution to my problem because the application thread has direct access to the parent API.
– user5265160
Nov 12 '18 at 17:30
add a comment |
Perform your intensive operation in another thread. This will not block the UI. If you need to call objects on UI thread from another thread than do exactly that - call them on UI thread. You can do this by doing an Invoke on current dispatcher.
await Application.Current.Dispatcher.BeginInvoke(() => SetPropertyOnUIThread());
Thanks for the suggestion. I can't run the operation on another thread, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.". The intensive operation involves accesses to the main application API, which is owned by the UI thread. The application is a plugin.
– user5265160
Nov 12 '18 at 14:05
Have you tried this? I am saying this because it seems like this solves the issue. You are getting this error because you are trying to update something between threads. This usually solves the problem. So for instance, if you have a view model that has a property that is binded to a progress level than changing this property from different thread will yield this error since the progress bar is owned by UI thread, BUT, if you call this property change on UI thread than it is okay.
– Rob
Nov 12 '18 at 14:11
I tried : await Application.Current.Dispatcher.BeginInvoke(new Action(() => PerformIntensiveOperation()));, however this still seems to block.
– user5265160
Nov 12 '18 at 15:06
When I run the WPF application on a separate thread, the above dispatcher invoke call works well and frees up the UI. This is a good solution to my problem because the application thread has direct access to the parent API.
– user5265160
Nov 12 '18 at 17:30
add a comment |
Perform your intensive operation in another thread. This will not block the UI. If you need to call objects on UI thread from another thread than do exactly that - call them on UI thread. You can do this by doing an Invoke on current dispatcher.
await Application.Current.Dispatcher.BeginInvoke(() => SetPropertyOnUIThread());
Perform your intensive operation in another thread. This will not block the UI. If you need to call objects on UI thread from another thread than do exactly that - call them on UI thread. You can do this by doing an Invoke on current dispatcher.
await Application.Current.Dispatcher.BeginInvoke(() => SetPropertyOnUIThread());
edited Nov 12 '18 at 13:49
answered Nov 12 '18 at 12:59
RobRob
1,0091022
1,0091022
Thanks for the suggestion. I can't run the operation on another thread, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.". The intensive operation involves accesses to the main application API, which is owned by the UI thread. The application is a plugin.
– user5265160
Nov 12 '18 at 14:05
Have you tried this? I am saying this because it seems like this solves the issue. You are getting this error because you are trying to update something between threads. This usually solves the problem. So for instance, if you have a view model that has a property that is binded to a progress level than changing this property from different thread will yield this error since the progress bar is owned by UI thread, BUT, if you call this property change on UI thread than it is okay.
– Rob
Nov 12 '18 at 14:11
I tried : await Application.Current.Dispatcher.BeginInvoke(new Action(() => PerformIntensiveOperation()));, however this still seems to block.
– user5265160
Nov 12 '18 at 15:06
When I run the WPF application on a separate thread, the above dispatcher invoke call works well and frees up the UI. This is a good solution to my problem because the application thread has direct access to the parent API.
– user5265160
Nov 12 '18 at 17:30
add a comment |
Thanks for the suggestion. I can't run the operation on another thread, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.". The intensive operation involves accesses to the main application API, which is owned by the UI thread. The application is a plugin.
– user5265160
Nov 12 '18 at 14:05
Have you tried this? I am saying this because it seems like this solves the issue. You are getting this error because you are trying to update something between threads. This usually solves the problem. So for instance, if you have a view model that has a property that is binded to a progress level than changing this property from different thread will yield this error since the progress bar is owned by UI thread, BUT, if you call this property change on UI thread than it is okay.
– Rob
Nov 12 '18 at 14:11
I tried : await Application.Current.Dispatcher.BeginInvoke(new Action(() => PerformIntensiveOperation()));, however this still seems to block.
– user5265160
Nov 12 '18 at 15:06
When I run the WPF application on a separate thread, the above dispatcher invoke call works well and frees up the UI. This is a good solution to my problem because the application thread has direct access to the parent API.
– user5265160
Nov 12 '18 at 17:30
Thanks for the suggestion. I can't run the operation on another thread, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.". The intensive operation involves accesses to the main application API, which is owned by the UI thread. The application is a plugin.
– user5265160
Nov 12 '18 at 14:05
Thanks for the suggestion. I can't run the operation on another thread, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.". The intensive operation involves accesses to the main application API, which is owned by the UI thread. The application is a plugin.
– user5265160
Nov 12 '18 at 14:05
Have you tried this? I am saying this because it seems like this solves the issue. You are getting this error because you are trying to update something between threads. This usually solves the problem. So for instance, if you have a view model that has a property that is binded to a progress level than changing this property from different thread will yield this error since the progress bar is owned by UI thread, BUT, if you call this property change on UI thread than it is okay.
– Rob
Nov 12 '18 at 14:11
Have you tried this? I am saying this because it seems like this solves the issue. You are getting this error because you are trying to update something between threads. This usually solves the problem. So for instance, if you have a view model that has a property that is binded to a progress level than changing this property from different thread will yield this error since the progress bar is owned by UI thread, BUT, if you call this property change on UI thread than it is okay.
– Rob
Nov 12 '18 at 14:11
I tried : await Application.Current.Dispatcher.BeginInvoke(new Action(() => PerformIntensiveOperation()));, however this still seems to block.
– user5265160
Nov 12 '18 at 15:06
I tried : await Application.Current.Dispatcher.BeginInvoke(new Action(() => PerformIntensiveOperation()));, however this still seems to block.
– user5265160
Nov 12 '18 at 15:06
When I run the WPF application on a separate thread, the above dispatcher invoke call works well and frees up the UI. This is a good solution to my problem because the application thread has direct access to the parent API.
– user5265160
Nov 12 '18 at 17:30
When I run the WPF application on a separate thread, the above dispatcher invoke call works well and frees up the UI. This is a good solution to my problem because the application thread has direct access to the parent API.
– user5265160
Nov 12 '18 at 17:30
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262104%2fc-sharp-wpf-accessing-objects-created-on-the-ui-thread-from-worker-thread-with%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What you are doing right now is creating a task on a threadpool thread that schedules work on UI thread so obviously this will block. It's the same as just calling
PerformIntensiveOperation()
– FCin
Nov 12 '18 at 12:25
You may not be able to, if interfacing with the larger app demands you do so from the UI thread. Try to run your intensive operation from a regular task, and only update your UI from the synchronization context.
– Nick
Nov 12 '18 at 12:25
Thanks. I can't run the operation from a task, as this will produce the error "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it."
– user5265160
Nov 12 '18 at 14:03