 |
|
 |
This is about as easy as it gets. Thanks for the code.
BTW, I had to add an Update() to actually get the form to update though, but works like a champ
|
|
|
|
 |
|
 |
oh my god, struggled for hours and hours with this until i found this tiny and working example
|
|
|
|
 |
|
 |
Mister, my code is similar like this:
In DoWork event , I create controls child, and in ProgressChanged event I try add controls to SplitterPanel, but the application not responds. I use InvokeRequired for controls child.
Any suggestions, please ? Thanks !!!
Private Sub bgCargaFichero_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgCargaFichero.DoWork
Try
'SplitContainer1.Panel1.SuspendLayout()
'SplitContainer1.Refresh()
' Procesar fichero
Me.ProcesarFicheroCargadoWork() ' IN THIS METHOD I CREATE CONTROLS Type = ContenedorVisorBase
'SplitContainer1.Panel1.ResumeLayout(False)
If bgCargaFichero.CancellationPending = True Then
e.Cancel = True
Else
e.Result = True
End If
End Sub
Private Sub bgCargaFichero_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgCargaFichero.ProgressChanged
Dim contenedorPagina As GRUPOBACKUP.Administrador.Util.Cliente.ControlesWindows.ContenedorVisorBase = Nothing
contenedorPagina = CType(e.UserState, GRUPOBACKUP.Administrador.Util.Cliente.ControlesWindows.ContenedorVisorBase)
If contenedorPagina IsNot Nothing Then
AddMiniaturaToPanel(contenedorPagina)
End If
=====
Delegate Sub AddMiniaturaToPanelDelegate2(ByVal cCTL As Control)
Private Sub AddMiniaturaToPanel(ByVal cCTL As Control)
If cCTL.InvokeRequired Then
Dim d As New AddMiniaturaToPanelDelegate2(AddressOf AddMiniaturaToPanel)
Me.Invoke(d, New Object() {cCTL})
Else
SplitContainer1.Panel1.Controls.Add(cCTL) ' Here, the application not responds !!!!
End If
End Sub
AE
|
|
|
|
 |
|
 |
i want to do same for my web project. there will not be windows.form.control like thing in web project, as i want to use setText function to set text of a label. can you help me in this regards? thanks.
Pravin Parmar,
PravinParmar.ce@gmail.com
|
|
|
|
 |
|
 |
First pardon my ignorance but i don't really understand why you need this to update a textbox. Can't you just do something like: this.TextBox1.Text = "text";
also, i was actually looking for something a bit different: let's say i have several class and i want update a textbox, do i have to pass back to the form class where the textbox is located to display the text or is there another way?
Thx for your help.
|
|
|
|
 |
|
 |
Hi,
I haven't tested it in the long run, but currentlly it runs fine.
The idea is to test the form for invocation, and if invocation is needed - invoke it and not each control in the form.
That way if the form is ready, you can access each control safelly.
Again - i haven't checked for the long run.
Here is the code:
System::Void MyForm::GuiCommandWorker_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e)
{
if (this->InvokeRequired)
{
this->Invoke(gcnew MethodInvoker(this, &MyForm::ExecuteGUICommand));
}
else
{
ExecuteGUICommand();
}
}
System::Void MyForm::ExecuteGUICommand()
{
if (this->comboBox1->Focused)
{
}
}
I hope it will help you.
ShloEmi.
|
|
|
|
 |
|
 |
Hi Daniel,
Nice article, one of many I've found on this subject. I did something similar for enabling/disabling controls.
Of course, the question is why do we have to do this at all? Why can't the control work it out itself. Surely it's a couple of lines of code for each method for a control for those guys at MS? Maybe a [SelfDelegate] attribute could get the compiler to do it.
Maybe someone can point me at a relevant discussion of why this can't be done?
Cheers,
Simon
|
|
|
|
 |
|
|
 |
|
 |
Hi,
Nice article
Regards,
--=A J E E S H=--
|
|
|
|
 |
|
 |
A much better solution would be to use the InvokeRequired property and Invoke() method (with or without an annonymous delegate).
Or you can use the AsyncOperation class, like the BackgroundWorker does.
|
|
|
|
 |
|
 |
Itay Sagui wrote: A much better solution would be to use the InvokeRequired property and Invoke() method (with or without an annonymous delegate).
Isn't that what he does?
|
|
|
|
 |
|
 |
Well, why to create a new delegate? Especially with 2.0 there's the new feature of anon delegates.
So you would just ctrl.Invoke(delegate() {ctrl.Text = "abc";}, null)
|
|
|
|
 |
|
 |
Yes you are right, however...
Invoke cannot work directly with anonimus methods:
error CS1503: Argument '1': cannot convert from 'anonymous method' to 'System.Delegate'
This is how you can overcome this problem:
void button1_OnClick(object sender, EventArgs e) { button1.Enabled = false; Thread t = new Thread(delegate() { Thread.Sleep(2000);//do some work BeginInvoke(new ThreadStart(delegate() { button1.Enabled = true; })); }); t.Start(); }
Cheers,
Oleg
|
|
|
|
 |
|
 |
Hi
I am trying to understand the concepts talked about here, and my code so far is:
lstResults.BeginInvoke(delegate() { lstResults.Columns.Clear(); }, null);
which is already contained in a BackgroundWorker thread, do I still have to create a new Thread(delegate()) with an BeginInvoke inside it, if so why as it is already running in a seperate thread..
(I am getting the error 'cannot convert from anonymous method to System.Delegate' which is why I ask)
Sorry, my brain is near exploding ;o
Thanks for all your help
-Dan
|
|
|
|
 |
|
 |
I may have found a more elegant solution to using anonymous methods with BeginInvoke
how about this?
[code]
lstResults.BeginInvoke((MethodInvoker)delegate() { lstResults.Columns.Clear(); }, null);
[/code]
|
|
|
|
 |
|
 |
The first message in this thread was a suggestion about usage of anonimus method instead of defining the delegate. And it was a good idea as in such case your code is much more readable/elegant.
The only problem is that BeginInvoke cannot process raw anonimus method so it has to be wrapped up into known delegate:
lstResults.BeginInvoke(new MethodInvoker(delegate() { lstResults.Columns.Clear(); }), null);
or type casted to this delegate (your code):
lstResults.BeginInvoke((MethodInvoker)delegate() { lstResults.Columns.Clear(); }, null);
Both ways are roughly equivalent.
My suggestion was to go further and avoid declaring custom delegate and reuse well-known existing one. The ThreadStart is a good candidate for this:
lstResults.BeginInvoke(new ThreadStart(delegate() { lstResults.Columns.Clear(); });
Note that the last parameter from your code (null) is not actually needed.
Cheers
|
|
|
|
 |
|
 |
Oleg Shilo wrote: My suggestion was to go further and avoid declaring custom delegate and reuse well-known existing one
I disagree; System.Windows.Forms.MethodInvoker is the best delegate type to use - that's what MS created it for.
|
|
|
|
 |
|
 |
Yes I agree, MethodInvoker is better.
I simply overlooked the fact that it is a well-known delegate. I thought it is a custom type declared in the author's code.
|
|
|
|
 |
|
 |
Hey, this is pretty common... threads come in from anywhere. I've found something like the following works pretty well too:
public void SomeMethod()
{
MethodInvoker method =
delegate
{
// Do the GUI updates
};
if (InvokeRequired) Invoke(method);
else method();
}
Effectively it's another anonymous delegate methodology. The keen thing is you don't have to worry about argument passing or anything, the compiler wraps everything up nicely. And, if by chance you're already on the GUI thread, you'll do the work immediately instead of scheduling it to be done and waiting for it. And of course, you can BeginInvoke if you really want to.
Neal
|
|
|
|
 |
|
 |
http://www.codeproject.com/cs/threads/SyncContextTutorial.asp
|
|
|
|
 |
|
 |
I'm with you. I've stopped using the "marshal everything using Invoke" approach because it is not sufficiently robust. Whenever I create custom controls now I use the Synchronization techniques built into .NET.
Still, this article presents a necessary step on the path to learning how to do that, so it's good information (particularly because I see the question "ZOMG WHY AM I GETTING A CROSS THREAD EXCEPTION?!?!" so often on forums).
|
|
|
|
 |
|
 |
(or even if you dont!) please leave a comment..
Cheers!
|
|
|
|
 |
|
 |
Nice class but with the advent of Version 2 of the framework can't this be achieved via the backgroundWorker component.
-- modified at 11:48 Monday 19th February, 2007
|
|
|
|
 |
|
 |
bombdrop wrote: Nice class but with the advent of Version 2 of the framework can't this be achieved via the backgroundWorker component.
D'oh, your kidding right?
Ah well, should still be usefull for 1.0/2.0, I am downloading 3.0 myself now to test this out, thanks for the headsup!
|
|
|
|
 |
|
 |
Sorry just reread that, did you mean to say with version 3?
version 2's backgroundworker doesn't support calls directly to the control from the threaded code, you've got to update the controls outside of the DoWork function that you define, in the operation completed or report progress function but I guess that is also another way of doing it.
|
|
|
|
 |