|
This is a repost of the question I responded to here[^].
|
|
|
|
|
I can't believe, this is the same guy.
|
|
|
|
|
I know, hence my comment.
|
|
|
|
|
Repost! do not repost your questions here.
***** Programme comme si dept soutien technique. est plein de tueurs en série et ils savent adresse de votre domicile. *****
|
|
|
|
|
When my background thread calls the following code,
public void Func(object Request, object Response)
{
if (this.InvokeRequired)
{
this.Invoke(new ResponseHandlerDelegate(ResponseHandler), new object[] { Request, Response });
return;
}
}
does the background thread get blocked at the Invoke call until the UI thread completes the function call?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Yes, the calling thread will block.
If this behaviour is not desired, you can circumvent it by using BeginInvoke instead of Invoke .
Ciao,
luker
|
|
|
|
|
And if I use BeginInvoke , can I "stack" multiple calls to BeginInvoke before any of them completes?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
You can, but be aware that this can lead to unpredictable results as they might not complete in the order you expect.
|
|
|
|
|
How true is this? Two calls to BeginInvoke from the same thread will execute in the order you called them in, I would imagine. And calls from different threads don't have a natural concept of before/after anyway, so it wouldn't matter.
|
|
|
|
|
They may start in the order you requested, but how do you know what order they finish in?
|
|
|
|
|
Correct me if I am wrong but all call will all run in the same thread.
That is in the thread of the control you are invoking.
As they are queued, I can't see how they could finish in a different order from the order they started.
|
|
|
|
|
|
I read the post I agree with you Luc. You can't predict in which order the methods will be run.
What I was trying to say is that they will complete in the order they start.
thread A: Control1.BeginInvoke DoSomething(1)
thread B: Control1.BeginInvoke DoSomething(2)
thread C: Control1.BeginInvoke DoSomething(3)
... sometime later
Control1's thread: Start Running DoSomething(1)
Control1's thread: End DoSomething(1)
Control1's thread: Start Running DoSomething(3)
Control1's thread: End DoSomething(3)
Control1's thread: Start Running DoSomething(2)
Control1's thread: End DoSomething(2)
I am not sure if it is clearer. What I want to say is that two calls to DoSomething won't happen simultaneously if they are called using Invoke.
|
|
|
|
|
Pascal Ganaye wrote: two calls to DoSomething won't happen simultaneously if they are called using Invoke.
Unless DoSomething() calls Application.DoEvents() (or something similar such as GetMessage), then the actions would probably still start in the intended order but not finish in that order, as now a later one could start and finish before an earlier one had a chance to finish. That is exactly why DoEvents is such an atrocious beast.
|
|
|
|
|
As Pascal says, all the UI updates will be in one thread, so once one has started, the rest must queue behind it.
|
|
|
|
|
Be careful! An Application.DoEvents() can cause the second call to overtake the first. And when it is not you to have placed such evil statements in the code, some Third Party components may contain them... Really a fun to debug that!
|
|
|
|
|
It's true. A while back we wrote an application that received inputs from a number of sensors, and these had to be plotted on a graph. The sensors were receiving on different threads, and items were being written to the display in the wrong order. While they were being logged in the right order, the person watching the display was seeing a distorted view of the sensor readings.
|
|
|
|
|
I'm curious, how did you solve that? Did you find some way to serialize the threads?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
We synchronised onto a queue and the data was retrieved in the correct order from the queue.
|
|
|
|
|
If the sensors are on different threads, the time they call BeginInvoke is not well defined in terms of order anyway. My question was about calling BeginInvoke multiple times from the same thread, and the order in which those invoked methods are run.
|
|
|
|
|
I've written an Outlook add-in that performs multiple jobs at the same time. Basically, I can highlight a stack of emails, right-click them, and tell the add-in to execute a standard process on SCCM objects with data contained in the emails.
The execution engine sets up a job object for each and every email in the list. Then, using the TPL, executes the entire stack of jobs, each job being a seperate task.
Well, each of those jobs can take about a minute to run. They report back status messages about what they are doing and what was and was not successful. Those status updates are setup by the task scheduler to execute on the UI thread where the DGV that shows the job queue state updates itself and shows the new data.
The goofy thing is that even though I can see the jobs executing and queueing up the status updates in a certain order (thank you VS2010!) those updates don't always execute in the same order they were queued up in. I haven't investigated why this occurs because, lets face it, it's just a status update. There's no pressing need for execution order here.
|
|
|
|
|
BobJanova wrote: How true is this?
Very.
Windows messages get collected in "event queues", and although they are called queues, the order of the elements isn't always maintained. It basically is, however there are certain exceptions, to name a few:
1. one can extract messages of a certain type, which basically means their type suddenly gets a higher priority; that is what the message filtering is about in e.g. GetMessage[^].
2. one can consolidate messages, e.g. Windows will postpone PAINT messages, and consolidate them into a single one if possible (which may enlarge the invalidation region). This normally is an optimization, as now fewer cycles are wasted on repainting an ever changing form.
|
|
|
|
|
Also be aware of any race conditions that may occur, and you may also get dead locks if you are not careful
|
|
|
|
|
Thanks, deadlocks is the main reason I've been investigating this approach!
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
I'm hoping someone can help because I'm stumped here.
I have a DataGridView that is populated with a SQL query. For simplicity's sake, let's say the SQL query is as follows:
SELECT Name, Number, Lookup FROM ValuesTable
Now, depending on the value of the 'Lookup' column, the value in the 'Number' column can either be a straight forward value (when Lookup==0) or a reference to a different table (when Lookup==1), in which case I want a ComboBox in the cell which shows the various options in that other table.
In other words, I can't really use DataGridViewComboBoxColumn because not all cells in the column are ComboBoxes , only those for which the Lookup value is 1.
So far, so good. In the DataBindingComplete event handler of the DataGridView I have code similar to the following to put a ComboBox (and populate it) into the 'Number' cell of each row that has a value of 1 in the 'Lookup' cell.
foreach (DataGridViewRow row in myDataGridView.Rows)
{
if (row.Cells["Lookup"].Value.ToString() != "0")
{
DataGridViewComboBoxCell myComboCell = new DataGridViewComboBoxCell();
using (SqlCommand mySqlCommand = new SqlCommand("SELECT Number, Text FROM LookupTable"))
{
using (SqlDataReader mySqlDataReader = sqlCommand.ExecuteReader())
{
DataSet ds1 = new DataSet();
DataTable dt1 = new DataTable();
ds1.Tables.Add(dt1);
ds1.Load(mySqlDataReader, LoadOption.PreserveChanges, ds1.Tables[0]);
myComboCell.DataSource = ds1.Tables[0];
myComboCell.DisplayMember = "Text";
myComboCell.ValueMember = "Number";
}
}
row.Cells["Value"] = newCell;
}
}
This sort of works, but not quite. All the appropriate cells in the DataGridView has a ComboBox inside them and the options of the ComboBox are those retrieved from the Lookup Table. But when an option is selected in a ComboBox and the focus is moved away from that cell, the actual value displayed in the cell is the number by which the value was looked up.
Also, if the DataGridView is populated (like described above), all the cells with ComboBoxes show the number that is stored in the 'Number' field of ValuesTable, not the 'Text' field of LookupTable like myComboCell.DisplayMember = "Text" dictates.
I'd really appreciate if someone could set me straight here.
|
|
|
|