2

I have an IPC communication between service and WinForm app. They intercommunicate with the help of the class, which utilizes the following interface:

public interface IBaseIPC
{

    Task<IPCConfig> GetConfig();
    Task<IPCInfo> Activate(IPCConfig ipcConfig);
    Task<IPCInfo> CancelActivation();
    Task<IPCInfo> GetInfo();
    Task<IPCInfo> Renew();
    Task<string> TestConnection(IPCConfig ipcConfig);
}

When these methods were synchronous, it worked fine. Now when return type switched from being IPCConfig to Task, I'm getting an exception Type 'System.Threading.Tasks.Task`1[[IPCInfo]' in Assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable. I see that it tries to serialize Task and fails. Is there any way around this issue?

KorsaR
  • 536
  • 1
  • 10
  • 26
  • Converting answer of kruoli to comment: *Maybe [this link](http://blogs.msdn.com/b/lucian/archive/2012/11/24/how-to-hibernate-async-methods-how-to-serialize-task.aspx) is a good explanation to this.* – hyde May 14 '14 at 14:38

1 Answers1

4

In what binary format would you send a task? There is no reasonable answer to that question. Therefore, you cannot send a task. Makes sense?

If your IPC library or framework is not async in nature you cannot return tasks to it. The framework has to understand them.

You are probably dealing with a sync-over-async scenario here. Read and understand this. You'll now recognize that you are not in a good situation. You get the worst of both worlds: no async IO benefits and more CPU usage.

What to do about it? Depends on your application. Maybe you shouldn't have gone async at all (because the framework does not support it).

usr
  • 168,620
  • 35
  • 240
  • 369
  • I'm using System.Runtime.Remoting. I'm making a UI to control service, which performs long running operations like communicating with remote server. The easiest way would be wrapping synchronous calls on the UI side, but that means that I'll have to duplicate the same code for the third time, because control class looks like this so far: [Serializable] public class ServiceControl : MarshalByRefObject, IBaseIPC public static IBaseIPC client; public Task GetConfig() { return client.GetConfig(); } ...} – KorsaR May 14 '14 at 14:35
  • AFAIK Remoting does not support asynchronous invocation. You're out of luck there. But why do you need to duplicate stuff? Just go synchronous everywhere you can and make the UI async (possibly by wrapping remoting calls with Task.Run, which is a valid strategy). – usr May 14 '14 at 14:39
  • Ok, Remoting supports async (http://msdn.microsoft.com/en-us/library/3k559b9a(v=vs.85).aspx) but I wouldn't use it. It is hard to use compared to just using await Task.Run in the UI. – usr May 14 '14 at 14:41
  • The reason I'm duplicating the code is that I have these methods realized in differnt client classes, which utilize the interface, then I have control class where I just go SomeMethod(){client.SomeMethod();}, and now I'll have to do Task.Run(()=>controlClass.SomeMethod()), so I thought maybe there is more elegant way to do this. – KorsaR May 14 '14 at 14:51
  • Without more code and context I cannot recommend anything. But I think you understand the issue now. Consider making everything synchronous except for the UI. Or, use WCF. Then you can make a synchronous service and an async client. – usr May 14 '14 at 14:53
  • See http://stackoverflow.com/a/22591516/122718. It makes the sync-async conversion issue go away. – usr May 14 '14 at 14:55