0

Let me start with the fact that similar forms of this question have been asked here, yet there are no working examples or useable answers to the subject (that I have been able to find). This post will attempt to provide a more concise example and advance a code block to that end. With reference to the following links that are similar though not conclusive/working examples.

similar link #1 Background worker

similar link #2 Multi Threading in web service

similar link #3 threading in ASP.net

similar link #4 acknowledge quickly but continue processing

Other links:

#1 Async Web service Call

#2 Calling Web Service Async functions from web page

#3 MS ThreadPool.QueueUserWorkItem Method

#4 MS Multithreading Walk Through Forms based

The problem is returning a response to a client consuming a web service so that the client can continue on its way while the web service completes processing tasks. The web service (after authentication) receives a file name from the client that should be retrieved from a distant ftp server. Once the file has been downloaded to the web service hosting server, the client can be released, as the file name was valid and has been copied to the local server.

The web server, after returning a simple 'true' Boolean response to the client, continues to crunch the downloaded file into a database and happily waits for the name of the next file.

The current call is a SOAP message and this is a traditional asmx web service.

Web Service:

<WebService details .....

Public sourceFile As String
Public myData as Boolean = False
    <WebMethod()> _
Public Function fileReady_Log2(ByVal user As String, ByVal PW As String, ByVal fileName As String) As String

    ' This function receives a web service call notifying this server to retrieve a file from a remote ftp server When the file is downloaded it is processed into this servers database.
    '
    ' This routine attempts to process an ASYNC routine to respond to the call and release the caller as soon as possible while continuing processing requirements.

    ' Validation removed for simplicity 
    If authorized Then
    ' Need to retrieve ftp server information and pull down the file and load it to the database.
        ' Call Async function

        sourceFile = filename

        Dim myObject = New ftpThread()
        myObject.SendDataAsync()

        ' Ok, now return the result to client.
        Return myData

        Dim ftpInfo As New ftpFileImport   '  continue with processing the uploaded file.
        results = ftpInfo.retrieveLogFile(fileName, deviceID, usr)


        Return results
    End If
    Return results
End Function

Currently this is the structure of the calling functions. I have tried a number of variations and decided now is a good time to stop and ask for help.

ftpThread.vb

Imports Microsoft.VisualBasic
Imports System.Threading


Public Class ftpThread
    Public Sub SendDataAsync()
        ThreadPool.QueueUserWorkItem(Sub(getFtpFileExists(sourceFile )))
    End Sub
End Class

I am also getting an Expression Expected exception on the word Sub above.

ftp functions This process works synchronously, need it to be asynchronous.

 Public Class ftpFileExistsCheck
      Public Sub getFtpFileExists()

        ' This all works without ASYNC 

           '  Retrieve FTP credentials from DB
           '  Set up ftp request
           '  download the file.

        '  But continuing process to DB at this point causes client to wait.
           myData  = True
     End Sub
 End Class

Thought I could figure this out from all I have read, but I just can't get past setting up the correct coding for ASYNC processing.

Community
  • 1
  • 1
htm11h
  • 1,739
  • 8
  • 47
  • 104
  • ASMX is a legacy technology, and should not be used for new development. WCF or ASP.NET Web API should be used for all new development of web service clients and servers. One hint: Microsoft has retired the [ASMX Forum](http://social.msdn.microsoft.com/Forums/en-US/asmxandxml/threads) on MSDN. – John Saunders May 13 '14 at 19:44
  • @John Saunders thanks, I am aware of the legacy tech. This is an enhancement to existing service because of the latency in processing larger files. Looking for a quick fix thought threading would do it. – htm11h May 13 '14 at 19:47
  • 1
    WCF supports one way messaging and compensated execution, which is exactly what you want. If you can, take John's recommendation and go with that instead. Frankly, I think only a custom implementation of a soap server and client could handle your scenario. – Michael J. Gray May 13 '14 at 19:47
  • Also, it's best not to perform long-running tasks in a web service. Instead, create a separate service and queue the work to the separate service. You may even queue the request using WCF, which the other service could self-host. – John Saunders May 13 '14 at 19:48
  • By long running its not expected to run longer than 1 minute or so, but that is long for the client app in our case. – htm11h May 13 '14 at 20:09

1 Answers1

2

In your ASMX service implementation, you should spin up a WCF client and invoke a one way service operation, passing the message straight across. This not only lets you solve your problem but when you can upgrade off of ASMX, you can go directly to the new but still familiar WCF endpoint.

  1. Implement a WCF service that mirrors your existing ASMX methods you need this kind of functionality in
  2. Make each service operation a one way operation
  3. Modify your existing ASMX service to consume the new WCF service and enjoy

Another alternative would be to use Windows Workflow Foundation (WF). WF lets you compensate an activity with the result of some service call. This means your service continues progressing until you need the value from the service, similar to how async and await works. You could create a WCF Workflow Service that represents your existing ASMX service and make the workflow a one way service operation, then fire off the entire workflow and dequeue work items in the workflow until completion or some expiration time or whatever criteria you need to indicate the workflow should stop expecting more work.

Michael J. Gray
  • 9,784
  • 6
  • 38
  • 67
  • you make this sound very easy. I must say I would really like to start working more on WCF solutions. I didn't think that I could code this same asmx (mirror) in WCF. Will that work? – htm11h May 13 '14 at 20:11
  • Will a One Way operation still provide some sort of response allowing the client to be aware that the request was received? This is necessary so that the client can delete the aforementioned ftp file from its local store. – htm11h May 14 '14 at 13:11
  • The WCF client waits for the remote server to close the connection and if no error is received between the request being sent and the connection being closed, it was accepted and is being processed. However, if you require that kind of resiliency, you should be using a service broker with ACID transactions and not relying on the remote server hardware to be stable enough to promise the client that it's OK to delete the local file(s). ACID transactions would ensure that the request is received, persisted, and if the power goes out or RAM falls out, everything is still recoverable on the server. – Michael J. Gray May 14 '14 at 16:49
  • Thanks Michael, I found this MSDN example http://msdn.microsoft.com/en-us/library/vstudio/ms742132(v=vs.90).aspx on compensation. Also, regarding transactions, since all of the processing is happening on the same server I am not sure there is a feasible solution, the client does not have resources to participate in the transaction, though I suppose a 2nd party server might able to be added. It maybe more feasible for this simple solution to fire off another test from the client with a simple Boolean response if the file made it to the web service. I am working on WCF service deployment now. – htm11h May 14 '14 at 20:29
  • @htm11h What I meant by transaction is that when you use a service broker, it does not tell the client it has accepted the request until it can guarantee that in the event of a failure that the service is left in a committed state. It doesn't wait until the entire operation is finished, but rather waits until the data is persisted to the server and has begun processing. Without ACID transactions, you could lose network connectivity before closing out the connection and the server may interpret that as aborting and the client would be none the wiser, happily deleting its files. – Michael J. Gray May 15 '14 at 01:44