In swing we have:
boolean SwingUtilities.isEventDispatchThread()
that returns true if it is called from swing event dispatch thread.
is there anything similar in javafx?
Yes you can check that you are in the FX thread with:
Platform.isFxApplicationThread();
Note that many UI interacting methods will throw an exception when called outside the FX thread.
Related
WinForms (VS2015 / .NET 4.6)
In my background thread
System.Threading.Tasks.Task.Run(() =>
{
...
_callback?.Progress("abcd");
...
});
I call the GUI (_callback), which implements an interface in the Form class.
Here, I modify textbox, progressbar, etc values.
void IWorkerCallback.Log(string message)
{
_textBoxLog.AppendText($"{message}{Environment.NewLine}");
++_progressBar.Value;
.... etc...
}
And all works fine!
If I break in with debugger, I could see that the Form.IWorkerCallback.Log() function is executed in the worker thread context (in Threads debug window).
It's said everywhere that you MUST change GUI items only on the GUI thread (where they are created), otherwise you get System.InvalidOperationException exception with cross-thread operation not valid.....
But it works fine for me.
Could you explain, why?
Thanks
Running UI calls from another thread is undefined behavior. It may work or not. To get consistent failure on cross-thread calls set Control.CheckForIllegalCrossThreadCalls = true; in the beginning of the program:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.checkforillegalcrossthreadcalls?view=netframework-4.8
From MSDN documentation:
When a thread other than the creating thread of a control tries to access one of that control's methods or properties, it often leads to unpredictable results. A common invalid thread activity is a call on the wrong thread that accesses the control's Handle property. Set CheckForIllegalCrossThreadCalls to true to find and diagnose this thread activity more easily.
On low Windows API level, cross-thread UI calls that don't use thread local storage or any other thread-specific resources, may be executed successfully. However, we still have thread synchronization problem, so result is also undefined.
I've been trying to implement a thread that runs in the background and updates a progress bar every second or so and following the example in the top answer to Delphi - timer inside thread generates AV. I notice that the proposed solution has an implementation of TThread.FinishThreadExecution. My IDE shows that my version of delphi supports that method, but I've been unable to find any documentation on it (google turns up 10 hits, none of which help, http://docwiki.embarcadero.com/ doesn't list that method under TThread. What is it for and when is it called?
FinishThreadExecution is not a method inherited from the TThread base class. It is only a method implemented in the derived class, TTimerThread.
The purpose of the method is to finish the execution of the thread in a proper way.
All FinishThreadExecution does is to call Terminate, which sets an internal flag in the TThread, plus sets the FTickEvent event to wake the thread. The thread execute method will then end and the thread will self destruct, since TThread.FreeOnTerminate is true.
I am trying to solve SL performance issues.
Up until now I had WCF calls which were executed by InvokeAsync.
Now, I changed it to use the BackgroundWorker.
Performance is greatly improved.
what can cause this? what does InvokeAsync did exactly that affected the UI thread? is it opening another UI thread?
Thanks
It comes down to Synchronization contexts. A thread may be associated with SynchronizationContext such as the DispatcherSynchronizationContext (which is the context of the UI thread and only contains this one thread). WCF will complete an operation in the same Synchronization context that it began in, if there is no synchronization context associated with the thread it will use any thread in the thread pool.
Hence if you have several outstanding async operations all invoked from the UI Thread then all those operations will want to run their completion code in the UI Thread. If a number of them complete at the same time the completion code will have to queue up waiting to be dispatched into this single UI thread.
Whereas when you invoke async operations in a Background worker its running in a thread from the thread pool and does not have special synchronisation context. When those operations complete their completion code may run on any available thread in the pool (of which there are several). So near simultaneous completions can all run in parallel on different threads.
In WPF and Silverlight i recommend to use SynchronazationContext to save the main thread, all other thread will use this instance of SynchronazationContext to access the main thread (UI). You use it in this manner (Note: i generated a method that do this and all other methods will access this method to update the UI):
SynchronazationContext ctx = null;
void DoSomething()
{
ctx = SynchronazationContext.Current;
//Some algorithm here
this.UpdatePic("Success !");
}
void ThreadProc()
{
SendOrPostCallback callBack = new SendOrPostCallback(UpdatePic);
ctx.Post(callBack, String.Format("Put here the pic path");
}
void UpdatePic(string _text)
{
//This method run under the main method
}
In .NET 5.0 you can call this complicated functions by mark the method as async and write 'await' when you call the synchronous method - that make the synchronous method as asynchronous method and update the UI with the main thread.
I am using a BackgroundWorker thread to do some work outside of the GUI thread in Silverlight 4. I would like to update widgets in the GUI context from the background thread, but have read warnings about doing so from Microsoft documentation. I understand that communicating from one thread to another throws an exception as only the GUI thread can update widgets, but isn't BeginInvoke provided for this:
// BackgroundWorker thread code...
Widget.Dispatcher.BeginInvoke(() => Status.Text = "Hello");
However, I am getting some unpredictable results in my worker code.
What is the proper way to cross communicate with the GUI thread ? Is it by passing a results collection out of the RunWorkerCompleted method ?
Thanks,
Scott
You don't call the GUI code directly.
You must fire and event to which the UI thread subscribes. It then does the marshalling necessary to update the UI safely.
There are plenty of questions (and answers) on this. See some of the "Related" questions in the right hand side bar.
I want a function like GetCurrentThread which returns a TThread object of the current executing thread. I know there is a Win32 API call GetCurrentThread, but it returns the thread Id. If there is a possibility to get TThread object from that ID that's also fine.
From your own answer, it seems maybe you only want to "determine if running in the main thread or not", in which case you can just use
if Windows.GetCurrentThreadId() = System.MainThreadID then
// ...
Although this won't work from a DLL created with Delphi if it was loaded by a worker thread.
The latest version of Delphi, Delphi 2009, has a CurrentThread class property on the TThread class.
This will return the proper Delphi thread object if it's a native thread. If the thread is an "alien" thread, i.e. created using some other mechanism or on a callback from a third party thread, then it will create a wrapper thread around the thread handle.
I'm using my own TThread descendent that registers itself in a global list, protected with a lock.
That way, a method in this descendent can walk the list and get a TThread give an ID.
Answering my own question. I guess it is not possible to get TThread object from ID. It is possible by using a global variable. Then comparing its handle and current thread id, one can determine if running in the main thread or not.
Wouldn't the current executing thread be the one you're trying to run a function from?
You could store the pointer of the TThread instance in the current thread's context via the TlsSetValue API call and then retrieve it using TlsGetValue. However, note that this will only work if you're trying to retrieve/store the TThread instance of the current thread.