Reputation: 4386
I have a button click event and inside I do a lot of work.
While I am doing this work (not from the UI project) I want to send messages to the UI to display to the user.
I am doing something like:
void Button_Click(object sender, EventArgs e)
{
DoMyWork(SendMessage);
{
public void SendMessage(string message)
{
TextBox1.Text = message + "\n";
}
and inside DoMyWork which is in another assembly i can call SendMessage which writes to the textbox. The messages will only display though when DoMyWork is complete.
How can I update TextBox1.Text on the fly without putting DoMyWork on a BackGround thread or do i have to put it on a BackGround thread? I do actually want to block the user from doing anything while DoMyWork is running
thanks
Upvotes: 2
Views: 823
Reputation: 976
The code I usually use for these kind of purposes is, it is originally for catching an UpdateStatus event from a child user control, but should work equally well for this.
Delegate Sub SetStatus(ByVal sender As Object, ByVal text As String)
Private Sub UpdateStatus_Event(ByVal sender As Object, ByVal str As String)
If tsStatus.InvokeRequired Then
Dim delStatus As New SetStatus(AddressOf UpdateStatus_Event)
Me.Invoke(delStatus, New Object() {sender, str})
Else
tsStatus.Text = str
Application.DoEvents()
End If
End Sub
Private Sub btn_Click(Byval sender as Object, Byval e as EventArgs) Handles btn1.Click
Dim oTh as New Threading.Thread(AddressOf WorkSub)
oTh.Start()
End Sub
Private Sub WorkSub()
ALotOfWork()
UpdateStatus_Event(btn1,"message")
End Sub
Upvotes: 0
Reputation: 392
either working this as a task or a background worker is the best solution. however you can pump messages from a regular thread to the UI...
you need a delegate sub - in the thread class
delegate void UpdateTextHandler(string msg);
code inside the thread
private void UpdateUI(string msg)
{
form1 f = My.Application.OpenForms("form1 ");
f.Invoke(new UpdateTextHandler(f.UpdateLabel), new object[] { msg });
}
code inside the UI
public void UpdateLabel(string msg)
{
label1.Text = msg;
}
Basically what you are trying to do here is just invoke the actual thread that has the UI and send it a message.
Unfortunately this doesn't really prevent the user from actually not being able to be anything. You would have to do through and disable controls as well.
Upvotes: 0
Reputation: 10536
Don't know about your developement status, you probably can't wait out for C# 5. But you should take a look at what's coming in this field with the "async - await" language features: http://msdn.microsoft.com/en-us/vstudio/async.aspx The current approach can be a bit hard to get you head around but they've really fixed that.
GJ
Upvotes: 0
Reputation: 2791
BackgroundWorker
is a great class. If you don't want the user to use the form while your process is running, you can set its Enabled
property to false
. But you don't want to block the UI thread during your long running process.
Upvotes: 0
Reputation: 48979
You really need to put long running operations on a separate thread. If you do not then the UI will become unresponsive and the user will think it has hung up. There are two common ways of getting the worker thread started.
There are two generally accepted methods for updating the UI safely with data generated by the worker thread.
Control.Invoke
.The BackgroundWorker
class inherently uses the push method (via Control.Invoke
) to report progress when using the ReportProgress
method in conjuction with the ProgressChanged
event.
Creating a thread manually allows you to have better control over how the UI and worker thread interactions take place in exchange for having to wire up all the plumbing yourself.
Since I do not know the details of the long running operation nor the nature of the messages that need to be displayed I cannot say for certain direction will work best for you. Starting off with BackgroundWorker
approach will probably be okay.
Upvotes: 1
Reputation: 1979
to update UI from another thread use Control.Invoke method - as previously mentioned. You may use BackgroundWorker to actually do work in another thread (otherwise UI becomes non-responsive) or roll your own thread - BackgroundWorker is just a helper class, but makes is much simpler
Upvotes: 0
Reputation: 13444
You need to place the code in a thread. Before launching the thread, disable any UI. When the thread dies, re-enable the UI.
When updating the UI from a worker thread, use the Invoke method on a Control, because all UI changes must come from the "UI Thread".
Upvotes: 2