problem understanding the template in c# and function

115 Views Asked by At

the documentation network and the most importantly documentation: SocketMessageLayer

in SocketMessageLayer there is function which I don't know how to call: public void AddPacketHandler<T>(Func<T, Task> asyncHandler, bool oneTime = false)

and this is how I was trying to call it:

    string str = "example";
    public SimpleSocket SS = new SimpleSocket();
    public SocketMessageLayer SML;
    
    
    
    public void Server(){
        //int port, bool singleConnection, int retryCount = 1
        SS.StartServer(21, false, 1);
        SML = new SocketMessageLayer(SS, true);
    }
    public void Client(){
        //string address, int port, bool needAck = true
        SS.StartClient("127.0.0.1", 21, true);
        SML = new SocketMessageLayer(SS, false);
    }
    
    
    
    public async Task SendMessage(string str){
        //public void AddPacketHandler<T>(Func<T, Task> asyncHandler, bool oneTime = false)
        await SML.AddPacketHandler<string>(SomeFunction("ClientSendToServer", await SML.Send(str) ), false  );
        //await SML.Send(str);
        
    }
    
    
    public void SomeFunction(string s, Task Tas){
        str = s;
    }

the problem is Argument 2: cannot convert from 'void' to 'System.Threading.Tasks.Task' in Send Message

what I'm trying to do is send message to server or from server to client. and I have problem understanding the basics.

2

There are 2 best solutions below

0
Johnathan Barclay On BEST ANSWER

There are number of issues here.

AddPacketHandler expects a Func<T, Task> delegate as it's first parameter, but you are invoking SomeFunction rather than passing it as a delegate.

This means that you are attempting to pass the return value of SomeFunction i.e. void, which isn't allowed, hence the compilation error.

Furthermore, Func<T, Task> is a delegate that accepts a single argument of type T and returns a Task.

Your SomeFunction method accepts two arguments of type T and Task and returns void, so it cannot be converted into a Func<T, Task> and cannot be passed as the first parameter.

What you could do is change the signature of SomeFunction to this:

public Task SomeFunction(string s)
{
    str = s;
    return Task.CompletedTask;
}

Which can be passed as follows:

public async Task SendMessage(string str)
{
    SML.AddPacketHandler<string>(SomeFunction, false);
    await SML.Send(str);        
}

And you probably want to pass "ClientSendToServer" to SendMessage rather than hardcoding it into that method:

await SendMessage("ClientSendToServer");
0
MestreDosMagros On

First and most important: Why you have to call AddPacketHandler?

Looking at this, the PacketHandler is not mandatory, so you can not add it if you don't need it, although, for registering the packet handler, you can do in a lot of ways, here is three examples:

Example 1

public class Program
    {
        private static List<Func<object, Task>> _handlers = new List<Func<object, Task>>();

        public static async Task Main(string[] args)
        {
            // you handler code goes here
            Func<string, Task> func = (str) => Task.Run(() => Console.WriteLine(str));           

            AddPacketHandler(func);
            await _handlers[0]("foo");
        }       

        public static void AddPacketHandler<T>(Func<T, Task> asyncHandler)
        {
            _handlers.Add((obj) => asyncHandler((T)obj));
        }
    }

Example 2

public class Program
    {
        private static List<Func<object, Task>> _handlers = new List<Func<object, Task>>();

        public static async Task Main(string[] args)
        {
            // you can create your handler here
            AddPacketHandler<string>(
                (str) =>
                {
                    return Task.Run(() => Console.WriteLine(str));
                });
            await _handlers[0]("foo");
        }

        public static void AddPacketHandler<T>(Func<T, Task> asyncHandler)
        {
            _handlers.Add((obj) => asyncHandler((T)obj));
        }
    }

Example 3

public class Program
    {
        private static List<Func<object, Task>> _handlers = new List<Func<object, Task>>();

        public static async Task Main(string[] args)
        {
            AddPacketHandler<string>(SomeFunction);         
            await _handlers[0]("foo");
        }

        // you handler code goes here
        private static Task SomeFunction(string s)
        {
            return Task.Run(() => Console.WriteLine(s));
        }

        public static void AddPacketHandler<T>(Func<T, Task> asyncHandler)
        {
            _handlers.Add((obj) => asyncHandler((T)obj));
        }
    }

The handle itself will be called by the library here

This code is based on the source code that is in the docs you informed, is always cool to give a look at that and see what the funcion actually does if you encounter yourself in some situation like this.