How to Write From one Thread to Another ?
12 posts
• Page 1 of 2 • 1, 2
How to Write From one Thread to Another ?
While running a multithread WPF application that has the GUI running on one thread and the business code on another, it is not allowed that the business thread writes directly to the GUI thread.
Question: How do we do that then ?
Thanks in advance,
Pierre Gilbert
Question: How do we do that then ?
Thanks in advance,
Pierre Gilbert
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: How to Write From one Thread to Another ?
When APL threads were new Jake solved this very problem very neatly for us by having the gui thread poll a set of nss each of which was allocated to another thread that wrote named variables to it asynchronously. The gui thread picked these up and displayed the data using a generic protocol.
No doubt more sophisticated solutions have become available since.
No doubt more sophisticated solutions have become available since.
-
Phil Last - Posts: 628
- Joined: Thu Jun 18, 2009 6:29 pm
- Location: Wessex
Re: How to Write From one Thread to Another ?
From a discussion with Michael Hughes it was recommended to use Data Binding or a Dispatcher to write values across threads.
Thanks Michael.
Thanks Michael.
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: How to Write From one Thread to Another ?
Like Michael told me, it is explained on the web that you need a dispatcher to access the properties of an object that is on another thread. This is such an example in C#:
From the WPF WS that Michael supplied me, I am trying to do a simplistic function that will do something similar in APL. So far I have this:
and ideally I would like to do the following:
What would be the correct way to write the function 'Dispatch' ?
Thanks in advance.
- Code: Select all
textBox.Dispatcher.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
textBox.Text = "Hello World";
}
));
From the WPF WS that Michael supplied me, I am trying to do a simplistic function that will do something similar in APL. So far I have this:
- Code: Select all
obj Dispatch action;ActionObj;delegate;⎕USING
action ← ⎕FX 'RunBackground' action
⎕USING ← 'System,System.dll' 'System.Windows,WPF/WindowsBase.dll' 'System.Windows.Threading,WindowsBase.dll'
action ← Type.GetType⊂'System.Action`1'
ActionObj ← action.MakeGenericType(⊂,Type.GetType⊂'System.Object')
delegate ← 2016⌶ActionObj(⎕OR'RunBackground')
obj.Dispatcher.BeginInvoke((DispatcherPriority.Normal)delegate)
and ideally I would like to do the following:
⎕USING←'System.Windows,WPF/PresentationFramework.dll'
win←⎕NEW Window
win Dispatch 'win.Title←''hello world'''
EXCEPTION
Dispatch[9] obj.Dispatcher.BeginInvoke((DispatcherPriority.Normal)delegate)
∧
⎕EXCEPTION.Message
VALUE ERROR
⎕EXCEPTION.Message
∧
What would be the correct way to write the function 'Dispatch' ?
Thanks in advance.
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: How to Write From one Thread to Another ?
Found it:
The problem that I see is that all actions will be put into the same function named 'RunBackground' and if you do a couple of rapid Dispatch one after each one the 'RunBackground' executed may not be the good one.
Is there a way to fix this ?
∇Dispatch[⎕]∇
[0] obj Dispatch action;ActionObj;delegate;⎕USING
[1]
[2] action←⎕OR ⎕FX'RunBackground'action
[3]
[4] ⎕USING←'System,System.dll' 'System.Windows.Threading,WindowsBase.dll'
[5]
[6] {}obj.Dispatcher.BeginInvoke(DispatcherPriority.Normal(⎕NEW Action action))
⎕USING ← 'System.Windows,WPF/PresentationFramework.dll'
win ← ⎕NEW Window
win Dispatch& 'win.Title←''hello world'''
win.Title
hello world
The problem that I see is that all actions will be put into the same function named 'RunBackground' and if you do a couple of rapid Dispatch one after each one the 'RunBackground' executed may not be the good one.
Is there a way to fix this ?
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: How to Write From one Thread to Another ?
Following from my previous post, looks like the Dispatcher idea can have currently some issues with the interpreter (based on my experience so far). I have resort to experiment with binding an apl variable to the DataContext of a form. The apl variable can contain a DataTable that can be used for binding (setting the DataContext directly with a DataTable across threads is not permitted in WPF). That way you can assign a DataTable to the apl variable across threads and the bind variable will change the DataContext with the value of the DataTable.
So far my experimentation has led me to the following function for this particular type of binding:
All this because I have not been able to do a simple/direct binding with 2015⌶.
Question: Is there a simpler way to do this type of binding ?
Thanks in advance
So far my experimentation has led me to the following function for this particular type of binding:
- Code: Select all
object BindVarNameToObjDataContext varName;binding;⎕USING
⍝ Binds a fully qualified existing apl variable name to the DataContext of a .Net objet.
⍝ The apl variable can contain a .Net object
⍝
⍝ varName = fully qualified existing apl variable name
⍝ object = .Net object
⎕USING←'System.Windows.Data,WPF/PresentationFramework.dll' 'System.Windows,WPF/PresentationFramework.dll'
⍝ This construction will set the 'Path' of the binding that is the name of the variable without the path
⍝ The 'Path' property is a 'System.Windows.PropertyPath' that is easier to set in the constructor than as a property.
binding←⎕NEW Binding(⊂,{(-⊥⍨⍵≠'.')↑⍵}varName) ⍝ varName is without the path here
binding.Source←2015⌶varName ⍝ varName is fully qualified with path here
binding.Mode←BindingMode.OneWay ⍝ Setup as One Way Binding
binding.UpdateSourceTrigger←UpdateSourceTrigger.PropertyChanged
⍝ Setting-up the Binding to the DataContext Property:
⍝ Looks like not all the elements have a DataContextProperty even if they show it in the intellisense.
⍝ We need to use instead a FrameworkElement that has always a DataContextProperty available to do the Binding.
⍝ Using object.SetBinding is very much faster than Data.BindingOperations.SetBinding(object FrameworkElement.DataContextProperty bd)
{}object.SetBinding(FrameworkElement.DataContextProperty binding)
All this because I have not been able to do a simple/direct binding with 2015⌶.
Question: Is there a simpler way to do this type of binding ?
Thanks in advance
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: How to Write From one Thread to Another ?
The way to do multiple bindings to variables is to bind a Namespace to a DataContext - not a DataTable
-
MikeHughes - Posts: 86
- Joined: Thu Nov 26, 2009 9:03 am
- Location: Market Harborough, Leicestershire, UK
Re: How to Write From one Thread to Another ?
Hello Michael, I was meaning if there is a simpler way to write the function 'BindVarNameToObjDataContext'.
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: How to Write From one Thread to Another ?
Yes, the namespace binding does use the ibeam
:Trap 0
{}Reset ns
:If 0=×/⍴type ⋄ obj.DataContext←(2015⌶)ns ⍝ Assign DataContext
:Else ⋄ obj.DataContext←type(2015⌶)ns ⍝ Assign DataContext with export definition
:EndIf
:Else ⋄ 'Trouble setting DataContext'⎕SIGNAL 90 ⍝ or throw exception
:EndTrap
{r}←Reset name
⍝ Resets the binding on the variable or namespace named in the argument
⍝
r←(2014⌶)name
⍝ c mjh 26Sep2014
:Trap 0
{}Reset ns
:If 0=×/⍴type ⋄ obj.DataContext←(2015⌶)ns ⍝ Assign DataContext
:Else ⋄ obj.DataContext←type(2015⌶)ns ⍝ Assign DataContext with export definition
:EndIf
:Else ⋄ 'Trouble setting DataContext'⎕SIGNAL 90 ⍝ or throw exception
:EndTrap
{r}←Reset name
⍝ Resets the binding on the variable or namespace named in the argument
⍝
r←(2014⌶)name
⍝ c mjh 26Sep2014
-
MikeHughes - Posts: 86
- Joined: Thu Nov 26, 2009 9:03 am
- Location: Market Harborough, Leicestershire, UK
Re: How to Write From one Thread to Another ?
Thanks Michael, in our case we want to show the value of a log file in our application. An item of the log file is some HTML with a message (color of the text will vary depending if it is an alarm or status) or a capture screen of the application (save as base64 in an inline png). Since the log file can be too big for the size of the workspace we save it in a CSV file outside the workspace (easy to add another item of the log that way too). We have found a third party dll that will read the CSV file and return a .net DataTable without having a single byte transiting in the workspace. Once we have the DataTable it is bind to a CollectionViewSource with a ListBox that contains some Syncfusion RichTextBoxAdv that will render the individual HTML items. The WPF ListBox will do some 'virtualizing' so we can see right away the items of the log that are in the view and the other items will be rendered only when we scroll (otherwise it is too long to wait for all the items to be rendered before viewing only the couple first ones).
We do on another thread the conversion of the CSV file to a DataTable and the binding hence my question on this forum.
It is a little bit hard to do the first time but the result is quite spectacular (the items of each day are group together in a custom .net Expander). There is a possibility that Dyalog will allow, in the future, the binding of a function. I think it would than be possible to bind a component file (via that function) and it will be much easier to do the same thing (looking forward for that Dyalog).
Thanks Michael for your help.
We do on another thread the conversion of the CSV file to a DataTable and the binding hence my question on this forum.
It is a little bit hard to do the first time but the result is quite spectacular (the items of each day are group together in a custom .net Expander). There is a possibility that Dyalog will allow, in the future, the binding of a function. I think it would than be possible to bind a component file (via that function) and it will be much easier to do the same thing (looking forward for that Dyalog).
Thanks Michael for your help.
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
12 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: Google [Bot] and 1 guest
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group