1

I try to build a simple async net tcp wcf tool which will open connection, send command, receive answer (a List with 0-10 string sentences), close connection.

The problem is, I get on (self-hosted) service side always - no matter what I try - "The I/O operation has been aborted because of either a thread exit or an application request", on client side of course the corresponding errors like "Existing connection was closed by remote host" and timeouts and so on.

I tried alot for the past days but I can't get rid of it.

Client Side (running on .NET 4.0, called around once a sec):

void callservice(string mykey) {
ServiceReference1.Client c = new ServiceReference1.Client(); 
c.GetDataCompleted += c_GetDataCompleted;                             
            try {
            c.GetDataAsync(mykey);
            }
            catch (FaultException aa)
            {                    
                c.Abort();                   
            }         
       }

 private void c_GetDataCompleted(object sender, ServiceReference1.GetDataCompletedEventArgs e)
    {
        ServiceReference1.Client c = (ServiceReference1.Client)sender;
        c.GetDataCompleted -= c_GetDataCompleted;                       
        try
        {
            if (e.Result != null && e.Result.Length > 0)
            {
              ... }
            c.Close();
         }
         catch (Exception) {
           c.Abort();
         }
      }

Server Side (running on .NET4.5):

   [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple,
InstanceContextMode=InstanceContextMode.PerCall,IncludeExceptionDetailInFaults=true)]
   public class Service1 : IMyService
    {
 public async Task<List<string>> GetData(string whatkey)
        {    
          List<string> mydatalist = new List<string>(); 
          mydatalist= await Task.Run<List<string>>(() =>
        {       
        ...
        });
    return mydatalist;
  }

What is going wrong there? Could it be that it is something not having to do with WCF at all? What could it be?

Server Side Exception:

System.Net.Sockets.SocketException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 The I/O operation has been aborted because of either a thread exit or an application request at System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted() at System.ServiceModel.Channels.SocketConnection.OnReceiveAsync(Object sender, SocketAsyncEventArgs eventArgs) at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncFailure(SocketError socketError, Int32 bytesTransferred, SocketFlags flags) at System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP) System.Net.Sockets.SocketException (0x80004005): The I/O operation has been aborted because of either a thread exit or an application request 3E3

One more interesting fact: SVCLogs show me that the I/O Exeption occurs after a timespan I can define in the

<connectionPoolSettings groupName="default" leaseTimeout="00:03:00" 
idleTimeout="00:02:39" maxOutboundConnectionsPerEndpoint="20" />

settings. In this example it will occur the first time after 00:02:39. My interpretation: It closes open connections due to the settings there and that causes the Exception since the ReceiveAsync operation i.ex. was still open.

My question is so far why does client.close() not close it completely and why isn't it finished yet when it is calling the c_getdatacompleted-event? Why does the operation "hang out" for 02:39 minutes and does not come to an end?

(If I would not force the close down via the connectionpool settings I end up with hundreds of open operations if I use netstat i.ex. to display)

Chris
  • 21
  • 1
  • 1
  • 4
  • Your server-side async usage makes no sense because Task.Run gains you nothing. The client side looks even weirder: you're wrapping an async call with Task.Run. Also the catch(FaultEx) will never be hit. You first need to understand how async works, I think, before you can proceed. It all looks slapped together without understanding. – usr Feb 21 '13 at 22:31
  • Ya, you are right. I took out the task.run on client side and will do on server side too then. But I dont think it is cos of useless task.runs ... – Chris Feb 21 '13 at 22:40
  • Who knows? You might be introducing threading races that cause strange internal errors. Is c_GetDataCompleted ever called? According to my understanding it should never be called. Please also post the full server-side and client-side stack traces. – usr Feb 21 '13 at 22:50
  • How did you generate the service reference for the client? Using VS or svcutil? And do you see the same thing working with .net 4.5 client? – Praburaj Feb 21 '13 at 23:43
  • I used VS to auto-create the event-based client part. I also took out the task-stuff on service side now with no change. I see that I/O exception in the svctrace logs. I did not yet test it with 4.5 on client side since I need to do the code in 4.0 for XP support. But I will test this later on with 4.5 too and post results here ... – Chris Feb 22 '13 at 05:18
  • You need to track down the cause of the error on the server side. Please post exception details including stack trace. – Stephen Cleary Feb 22 '13 at 14:57
  • I added the exception details in my question. – Chris Feb 22 '13 at 18:05
  • Is your `IMyService.GetData` contract actually defined as returning a `Task>` that presumably gives the client a `Task` that is running on the server? – Peter Ritchie Feb 22 '13 at 18:13
  • [OperationContract(AsyncPattern=true)] Task> GetData(string mykey); – Chris Feb 22 '13 at 18:23

1 Answers1

0

Async WCF operations (AsyncPattern=true) are implemented with the Asynchronous Programming Model. That is, you implement an operation ("Operation") with two asynchronous operations ("BeginOperation" and "EndOeration"). The client can wrap those operations with a Task (presumably with the FromAsync overload)

For example:

[ServiceContract]
public interface ISampleTaskAsync
{
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginDoWork(int count, AsyncCallback callback, object state);

    int EndDoWork(IAsyncResult result);
}

The WCF contract does not return a Task<T>

Then, on the client you could do something like:

var proxy = new Services.SampleTaskAsyncClient();
object state = "This can be whatever you want it to be";

var task = Task<int>.Factory.FromAsync(proxy.BeginDoWork, 
    proxy.EndDoWork, 10, state);

For more information see:

If you want to use Task<T>, I believe you don't need AsyncPattern=true.

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
  • To be honest I had implemented this also in my search for a solution (I also know the pages you posted and the source that code is from), but since this threw the same errors (I/O Exception) I changed back to the easier task model instead of the IAsync-Pattern. Or I did something wrong, but it worked, just I still got these IO exceptions in my svctraceviewer ... – Chris Feb 22 '13 at 18:45
  • I just don't know what `AsyncPattern=true` on an operation that returns `Task` would do... – Peter Ritchie Feb 22 '13 at 18:48
  • It "appears" like the server is existing before the operation has completed. That could happen if the client closed the connection before it got the result... – Peter Ritchie Feb 22 '13 at 18:49
  • But how? I call client.close in the event c_getdatacompleted ... that means to me: Transfer is completed, right? Btw I also tried with .NET4.5 on client side. I still get the exceptions (not on each call, just every few minutes, like before). – Chris Feb 22 '13 at 19:02
  • I edited question with one more detail about the connectionpool idletime settings ... – Chris Feb 22 '13 at 20:52