patterncsharpMinor
Using Delegates and BeginInvoke with .NET 2.0 WebServices
Viewed 0 times
begininvokewithwebservicesnetdelegatesusingand
Problem
I'm attempting to implement a simple long-polling/comet/reverse AJAX solution, and came across the concept of delegates, specifically with the
The goal, of course, is to offload the actual processing from IIS processes onto other framework processes, for a reduction in server load when waiting on a long-poll request for data. I can't have gotten this right, but I want to know why and at least get some direction in how it might be better accomplished (not necessarily a solution, but maybe an article or some documentation).
The Web Service code:
```
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Threading
Imports System.Runtime.InteropServices
_
_
_
Public Class WebService
Inherits System.Web.Services.WebService
_
Public Function HelloWorld() As String
Dim threadId As Integer
Dim thing As New Things
Dim caller As New AsyncDoStuff(AddressOf thing.doStuff)
Dim result As IAsyncResult = caller.BeginInvoke(3000, threadId, Nothing, Nothing)
result.AsyncWaitHandle.WaitOne()
Dim returnValue As String = caller.EndInvoke(threadId, result)
result.AsyncWaitHandle.Close()
Return returnValue
End Function
End Class
Public Class Things
Public Function doStuff(ByVal callDuration As Integer, ByRef threadId As Integer) As String
' Imagine this method was accessing a database, looking for new information, and returning when it found some
Thread.Sleep(callDuration)
threadId = Thread.CurrentThread.ManagedThreadId()
Return String.Format("My call time was {0}.", callDuration.ToString())
End Function
End Class
Public Delegate Function AsyncDoStuff(ByVal callDuration As Integer, ByRef threadID
BeginInvoke and EndInvoke methods. I've built a Web Service that uses these concepts, but, having never used these, they make me a little nervous, and I have my doubts as to whether they are actually what I want.The goal, of course, is to offload the actual processing from IIS processes onto other framework processes, for a reduction in server load when waiting on a long-poll request for data. I can't have gotten this right, but I want to know why and at least get some direction in how it might be better accomplished (not necessarily a solution, but maybe an article or some documentation).
The Web Service code:
```
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Threading
Imports System.Runtime.InteropServices
_
_
_
Public Class WebService
Inherits System.Web.Services.WebService
_
Public Function HelloWorld() As String
Dim threadId As Integer
Dim thing As New Things
Dim caller As New AsyncDoStuff(AddressOf thing.doStuff)
Dim result As IAsyncResult = caller.BeginInvoke(3000, threadId, Nothing, Nothing)
result.AsyncWaitHandle.WaitOne()
Dim returnValue As String = caller.EndInvoke(threadId, result)
result.AsyncWaitHandle.Close()
Return returnValue
End Function
End Class
Public Class Things
Public Function doStuff(ByVal callDuration As Integer, ByRef threadId As Integer) As String
' Imagine this method was accessing a database, looking for new information, and returning when it found some
Thread.Sleep(callDuration)
threadId = Thread.CurrentThread.ManagedThreadId()
Return String.Format("My call time was {0}.", callDuration.ToString())
End Function
End Class
Public Delegate Function AsyncDoStuff(ByVal callDuration As Integer, ByRef threadID
Solution
This Stack Overflow answer to the question "Is there a VB.NET equivalent of C# out parameters" is pretty clear:
No, there is no equivalent construct that allows a non-initialised variable to be passed to a method without a warning [...]
However specifying the `
No, there is no equivalent construct that allows a non-initialised variable to be passed to a method without a warning [...]
However specifying the `
attribute, despite being ignored by VB (ByRef is all you need, really), does allow a C# client to use it as an out parameter - so good call then!
Declaring the delegate at the bottom of the module, after it's being used, makes it uselessly confusing and prompts for unnecessary scrolling; I would have put it at the top... actually, I would have made the delegate a public member of the WebService class:
Public Class WebService
Inherits System.Web.Services.WebService
Public Delegate Function AsyncDoStuff(ByVal callDuration As Integer, ByRef threadID As Integer) As String
'...
I very, very seldom declare my own delegate types, if at all. I don't like ref ByRef and out parameters either - I think they should be avoided.
In this case I would have gone with a Func (please excuse the C# notation), where the int parameter is the callDuration, and the AsyncStuffResult is a class that encapsulates everything you want to return from the function call - whatever that is.
This way if/when you need to return more things, your signature doesn't need to change, you only add new members to your result class - note that the EventArgs` class fulfills the same goal.Public Class AsyncStuffResult
'- expose ThreadId as a get-only property
'- expose your String result as a get-only property, too
'- expose a constructor to assign the members
End ClassCode Snippets
Public Class WebService
Inherits System.Web.Services.WebService
Public Delegate Function AsyncDoStuff(ByVal callDuration As Integer, <Out()> ByRef threadID As Integer) As String
'...Public Class AsyncStuffResult
'- expose ThreadId as a get-only property
'- expose your String result as a get-only property, too
'- expose a constructor to assign the members
End ClassContext
StackExchange Code Review Q#4516, answer score: 3
Revisions (0)
No revisions yet.