You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello. I was wondering if it is possible to use the await operator in [JsonRpcMethod] methods?
Inside the [JsonRpcMethod] I would like to call asynchronous methods and return Task<T> from the function. But this approach throws an exception. All I could do was call synchronous versions of the functions and return Task.FromResult from the function.
Some examples:
using AustinHarris.JsonRpc;
object[] services = new object[] { new ExampleService() };
for (string line = Console.ReadLine(); !string.IsNullOrEmpty(line); line = Console.ReadLine())
{
try
{
var response = await JsonRpcProcessor.Process(line);
Console.WriteLine(response);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public class ExampleService : JsonRpcService
{
[JsonRpcMethod]
private async Task<double> DoSomethingAsync(double l, double r) // {'method':'DoSomethingAsync','params':[1.0,2.0],'id':1}
{
return await Worker.SummAsync(l, r);
}
}
public class Worker
{
public static async Task<double> SummAsync(double a, double b)
{
await Task.Delay(1000);
return await Task.FromResult(a + b);
}
}
Exception:
Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'Task' with type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.Double,ExampleService+<DoSomethingAsync>d__0]'. Path 'StateMachine.<>t__builder'.
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value)
at AustinHarris.JsonRpc.JsonRpcProcessor.ProcessSync(String sessionId, String jsonRpc, Object jsonRpcContext, JsonSerializerSettings settings)
at AustinHarris.JsonRpc.JsonRpcProcessor.<>c.<Process>b__3_0(Object _)
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at Program.<Main>$(String[] args) in D:\Work\other\JsonRpcNetAsync\JsonRpcNetAsync\Program.cs:line 9
Working example:
using AustinHarris.JsonRpc;
object[] services = new object[] { new ExampleService() };
for (string line = Console.ReadLine(); !string.IsNullOrEmpty(line); line = Console.ReadLine())
{
try
{
Task<string> task1 = JsonRpcProcessor.Process(line);
Task<string> task2 = JsonRpcProcessor.Process(line);
Task<string> task3 = JsonRpcProcessor.Process(line);
Task<string>[] tasks = [task1, task2, task3];
string[] result = await Task.WhenAll(tasks);
foreach (string res in result) Console.WriteLine(res);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public class ExampleService : JsonRpcService
{
[JsonRpcMethod]
private Task<double> DoSomethingAsync(double l, double r) // {'method':'DoSomethingAsync','params':[1.0,2.0],'id':1}
{
return Task.FromResult(Worker.SummSync(l, r));
}
}
public class Worker
{
public static double SummSync(double a, double b)
{
Thread.Sleep(10000);
return a + b;
}
}
If I understand correctly, calling JsonRpcProcessor.Process(line) runs in a separate thread, so blocking synchronous methods do not block the calling thread. But in the future, I might want to call asynchronous methods, and I was wondering if it is possible to do so using your framework? Thanks a lot for your answer!
The text was updated successfully, but these errors were encountered:
This project does not currently have native support for the async and await style JsonRpcMethods as it was created long before async and await keywords were added to the language, but a workaround does exist.
Could you give something like the following example a try?:
public class ExampleService : JsonRpcService
{
[JsonRpcMethod]
private double DoSomethingAsync(double l, double r) // {'method':'DoSomethingAsync','params':[1.0,2.0],'id':1}
{
// Call the async method and wait for it synchronously using GetAwaiter().GetResult()
return Worker.SummAsync(l, r).GetAwaiter().GetResult();
}
}
public class Worker
{
// An asynchronous method that uses Task.Delay to simulate async work
public static async Task<double> SummAsync(double a, double b)
{
await Task.Delay(1000); // Simulate some asynchronous delay
return a + b;
}
}
If you would like to add native support for async and await as handler functions, then some places to start looking at the code would be:
Hello. I was wondering if it is possible to use the await operator in
[JsonRpcMethod]
methods?Inside the
[JsonRpcMethod]
I would like to call asynchronous methods and returnTask<T>
from the function. But this approach throws an exception. All I could do was call synchronous versions of the functions and returnTask.FromResult
from the function.Some examples:
Exception:
Working example:
If I understand correctly, calling
JsonRpcProcessor.Process(line)
runs in a separate thread, so blocking synchronous methods do not block the calling thread. But in the future, I might want to call asynchronous methods, and I was wondering if it is possible to do so using your framework? Thanks a lot for your answer!The text was updated successfully, but these errors were encountered: