|
-
Sep 21st, 2015, 09:00 AM
#1
Thread Starter
Frenzied Member
raiseevent from async method?
Hi!
I am working in some old code that we are moving into the world of async await. I have hit a problem with a class that notifies subscribers of status changes through RaiseEvent. The problem is that all the events are queued up on the caller side like this:
Code:
addhandler myWorker.ReportProgressEvent, addressof CollectProgress
dim result = await myWorker.DoWork
' Finished
Debug.Write(result.Message)
private sub CollectProgress(i as integer)
Debug.Write("status is:" & i)
end sub
What happens is that the async method is called, it does its work and raises 10 ReportProgressEvent and then finishes, and THEN the CollectProgress method is raised 10 times...
Is there a way to fix this behavior (easily)? I have looked into the Progress(of T) class, but not sure if it is overkill or not?
Any thoughts?
/H
-
Sep 21st, 2015, 10:35 AM
#2
Re: raiseevent from async method?
I don't understand what's going on. I don't know what your myWorker variable represents. It isn't any class listed on MSDN, becuase "ReportProgressEvent" doesn't return any results (and isn't named like any other event in the framework.)
DoWork looks familiar as a method of BackgroundWorker, but my psychic powers tell me that myWorker isn't BackgroundWorker. All I can say is what you have written is somehow making your UI thread hang instead of processing the event handlers. It could be because events raised from a worker thread are raised in a "free threading" context. I don't know. I'd have to see more code to explain what's going wrong. I'd like to solve that mystery, so please post what you have!
In the meantime, here's an example of how task-based progress reporting is supposed to look when you want to report progress. Progress(T) isn't really all that hard to use, and it makes sure things go tot he right threads for you. Create a new Windows Forms project, drop a TextBox and a Button onto the form, then paste this in:
Code:
Public Class Form1
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' This makes sure if the user clicks the button twice really fast, we still only execute the task once.
If Not Button1.Enabled Then
Return
End If
Button1.Enabled = False
' Progress(Of T) needs something to do when progress changes. You might choose to use a lambda
' or you might choose to add an event handler. I like lambdas when it's short.
Dim progressReporter As New Progress(Of Integer)(Sub(progress)
TextBox1.Text = String.Format("I'm at {0}%!", progress)
End Sub)
' This lets the worker thread do its thing, and we'll come back to the next line of code when it finishes.
' However, our Progress(Of T) might raise its event while we wait.
Dim result = Await DoWork(progressReporter)
' If we get here, the task finished without throwing exceptions, so yay!
TextBox1.Text = String.Format("The computer counted to {0}!", result)
End Sub
Private Async Function DoWork(ByVal progressReporter As IProgress(Of Integer)) As Task(Of Integer)
Return Await Task.Run(Function() As Integer
Dim stopwatch = System.Diagnostics.Stopwatch.StartNew()
For i As Integer = 1 To 10
progressReporter.Report(i * 10)
System.Threading.Thread.Sleep(1000)
Next
Return CInt(stopwatch.ElapsedMilliseconds)
End Function)
End Function
End Class
Something about your code is different than this. I'd like to know what, because the more I learn about the mistakes people make the better I get at psychically predicting what went wrong in other threads like this The behavior you describe indicates that your UI thread is somehow busy until your DoWork() method finishes. Perhaps you have some other thing happening that slows it down?
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Sep 21st, 2015, 01:59 PM
#3
Re: raiseevent from async method?
Even after readin Sitten's post, I'm not convinced it isn't a BGW ... but he's right in that there is no ReportProgressEvent ... the BGW does have a ReportProgrss event though... so maybe that's what was intended. On the other hand the CollectProcess handler it is hooked up to doesn't have the correct stub... in which case I have to retract my previous statement and agree with Sitten, that I don't think we really have the foggiest notion what you are attempting here.
-tg
-
Sep 22nd, 2015, 09:49 PM
#4
Re: raiseevent from async method?
 Originally Posted by techgnome
the BGW does have a ReportProgrss event though
Nope. ReportProgress is the method you call to raise the ProgressChanged event. This can't be a BackgroundWorker because DoWork is an event in that case, where here its an async method.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|