Добавление IDisposable

This commit is contained in:
2025-02-23 10:18:38 +03:00
parent b6226b68c9
commit ae4979c9f9
12 changed files with 207 additions and 72 deletions
+15 -1
View File
@@ -31,7 +31,21 @@ namespace Example.Backend
public async Task AsyncTest(CancellationToken token) public async Task AsyncTest(CancellationToken token)
{ {
await Task.Delay(TimeSpan.FromSeconds(5), token); Console.WriteLine("Async Test");
for (int i = 0; i < 10; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Waiting canceled");
return;
}
Console.WriteLine("Waiting...");
await Task.Delay(1000);
}
Console.WriteLine("Waited until the end");
} }
} }
} }
+6
View File
@@ -1,3 +1,4 @@
using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Example.Shared; using Example.Shared;
@@ -18,5 +19,10 @@ namespace Example.Backend
// throw new Exception("The method or operation is not implemented."); // throw new Exception("The method or operation is not implemented.");
return new Page {Text = text}; return new Page {Text = text};
} }
public void Dispose()
{
Console.WriteLine("Dispose printer with name {0}", Name);
}
} }
} }
+5
View File
@@ -20,6 +20,11 @@ namespace Example.Frontend
await Task.Yield(); await Task.Yield();
return new ClientBasedPage(); return new ClientBasedPage();
} }
public void Dispose()
{
}
} }
public class ClientBasedPage : IPage public class ClientBasedPage : IPage
+37 -22
View File
@@ -3,6 +3,7 @@ using System.Diagnostics;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Example.Frontend; using Example.Frontend;
using Example.Shared; using Example.Shared;
using mROA.Codegen; using mROA.Codegen;
@@ -44,36 +45,50 @@ class Program
//правильный порядок команд 8-5-10-7 //правильный порядок команд 8-5-10-7
var printer = factory.Create("Test"); var printer = factory.Create("Test");
Console.WriteLine("Printer created"); using (var disposingPrinter = printer.Value)
Thread.Sleep(100); {
Console.WriteLine("Printer created");
Thread.Sleep(100);
var name = printer.Value.GetName(); var name = disposingPrinter.GetName();
Console.WriteLine("Printer name : {0}", name); Console.WriteLine("Printer name : {0}", name);
Thread.Sleep(100);
factory.Register(new SharedObject<IPrinter>(new ClientBasedPrinter())); Thread.Sleep(100);
Console.WriteLine("Registered printer");
Thread.Sleep(100); factory.Register(new SharedObject<IPrinter>(new ClientBasedPrinter()));
Console.WriteLine("Registered printer");
Thread.Sleep(100);
var registred = factory.GetFirstPrinter(); var registred = factory.GetFirstPrinter();
Console.WriteLine("First printer"); Console.WriteLine("First printer");
Thread.Sleep(100); Thread.Sleep(100);
Console.WriteLine(registred.Value); Console.WriteLine(registred.Value);
Console.WriteLine("Collecting all printers"); Console.WriteLine("Collecting all printers");
var names = factory.CollectAllNames(); var names = factory.CollectAllNames();
Thread.Sleep(100); Thread.Sleep(100);
Console.WriteLine(string.Join(", ", names)); Console.WriteLine(string.Join(", ", names));
var page = printer.Value.Print("Test Page", new CancellationToken()).GetAwaiter().GetResult(); var page = disposingPrinter.Print("Test Page", new CancellationToken()).GetAwaiter().GetResult();
Console.WriteLine("Page printed"); Console.WriteLine("Page printed");
var data = page.Value.GetData(); var data = page.Value.GetData();
Console.WriteLine("Data : {0}", Encoding.UTF8.GetString(data)); Console.WriteLine("Data : {0}", Encoding.UTF8.GetString(data));
}
// var loadSingleton = context.GetSingleObject(typeof(ILoadTest)) as ILoadTest;
var loadSingleton = context.GetSingleObject(typeof(ILoadTest)) as ILoadTest;
var cts = new CancellationTokenSource();
var token = cts.Token;
var t = Task.Run(async () => await loadSingleton!.AsyncTest(token));
Thread.Sleep(5000);
cts.Cancel();
Console.WriteLine($"Token state {cts.Token.IsCancellationRequested}");
Console.ReadKey();
// //
// const int iterations = 10000; // const int iterations = 10000;
// var timer = Stopwatch.StartNew(); // var timer = Stopwatch.StartNew();
+2 -1
View File
@@ -1,3 +1,4 @@
using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using mROA.Implementation; using mROA.Implementation;
@@ -6,7 +7,7 @@ using mROA.Implementation.Attributes;
namespace Example.Shared namespace Example.Shared
{ {
[SharedObjectInterface] [SharedObjectInterface]
public interface IPrinter public interface IPrinter : IDisposable
{ {
string GetName(); string GetName();
Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken); Task<SharedObject<IPage>> Print(string text, CancellationToken cancellationToken);
+3
View File
@@ -233,6 +233,9 @@ namespace mROA.Codegen
public MethodInfo GetMethod(int id) public MethodInfo GetMethod(int id)
{{ {{
if (id == -1)
return typeof(IDisposable).GetMethod(""Dispose"");
if (_methods.Count <= id) if (_methods.Count <= id)
return null; return null;
@@ -21,6 +21,8 @@ namespace mROA.Implementation.Backend
public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository, public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository,
IRepresentationModule representationModule) IRepresentationModule representationModule)
{ {
Console.WriteLine(command.GetType().Name);
if (_cancellationRepo is null) if (_cancellationRepo is null)
throw new NullReferenceException("Method repository was not defined"); throw new NullReferenceException("Method repository was not defined");
@@ -30,6 +32,19 @@ namespace mROA.Implementation.Backend
if (contextRepository is null) if (contextRepository is null)
throw new NullReferenceException("Context repository was not defined"); throw new NullReferenceException("Context repository was not defined");
if (command is CancelRequest)
{
Console.WriteLine("Final cancelling request");
var cts = _cancellationRepo.GetCancellation(command.Id);
cts.Cancel();
_cancellationRepo.FreeCancelation(command.Id);
return new FinalCommandExecution
{
Id = command.Id,
CommandId = command.CommandId
};
}
var currentCommand = _methodRepo.GetMethod(command.CommandId); var currentCommand = _methodRepo.GetMethod(command.CommandId);
if (currentCommand == null) if (currentCommand == null)
throw new Exception($"Command {command.CommandId} not found"); throw new Exception($"Command {command.CommandId} not found");
@@ -48,7 +63,14 @@ namespace mROA.Implementation.Backend
return ExecuteAsync(currentCommand, context, parameter, command, _cancellationRepo, return ExecuteAsync(currentCommand, context, parameter, command, _cancellationRepo,
representationModule); representationModule);
return Execute(currentCommand, context, parameter, command); var result = Execute(currentCommand, context, parameter, command);
if (command.CommandId == -1)
{
contextRepository.ClearObject(command.ObjectId);
}
return result;
} }
private static ICommandExecution Execute(MethodInfo currentCommand, object context, object? parameter, private static ICommandExecution Execute(MethodInfo currentCommand, object context, object? parameter,
@@ -57,9 +79,10 @@ namespace mROA.Implementation.Backend
try try
{ {
var finalResult = currentCommand.Invoke(context, parameter is null var finalResult = currentCommand.Invoke(context, parameter is null
? new object[0] ? Array.Empty<object>()
: new[] : new[]
{ parameter }); { parameter });
return new TypedFinalCommandExecution return new TypedFinalCommandExecution
{ {
CommandId = command.CommandId, Result = finalResult, CommandId = command.CommandId, Result = finalResult,
@@ -77,13 +100,14 @@ namespace mROA.Implementation.Backend
} }
} }
private static ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter, private ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
ICallRequest command, ICancellationRepository cancellationRepository, ICallRequest command, ICancellationRepository cancellationRepository,
IRepresentationModule representationModule) IRepresentationModule representationModule)
{ {
var tokenSource = new CancellationTokenSource(); var tokenSource = new CancellationTokenSource();
cancellationRepository.RegisterCancellation(command.Id, tokenSource); cancellationRepository.RegisterCancellation(command.Id, tokenSource);
var token = tokenSource.Token; var token = tokenSource.Token;
token.Register(() => Console.WriteLine($"Cancellation requested check {command.Id}"));
try try
{ {
var result = (Task)currentCommand.Invoke(context, parameter is null var result = (Task)currentCommand.Invoke(context, parameter is null
@@ -94,11 +118,16 @@ namespace mROA.Implementation.Backend
result.ContinueWith(_ => result.ContinueWith(_ =>
{ {
if (token.IsCancellationRequested)
return;
var payload = new FinalCommandExecution var payload = new FinalCommandExecution
{ {
Id = command.Id, Id = command.Id,
CommandId = command.CommandId CommandId = command.CommandId
}; };
_cancellationRepo.FreeCancelation(command.Id);
var multiClientOwnershipRepository = var multiClientOwnershipRepository =
TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository; TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository;
multiClientOwnershipRepository?.RegisterOwnership(representationModule.Id); multiClientOwnershipRepository?.RegisterOwnership(representationModule.Id);
@@ -121,7 +150,7 @@ namespace mROA.Implementation.Backend
} }
} }
private static ICommandExecution TypedExecuteAsync(MethodInfo currentCommand, object context, object? parameter, private ICommandExecution TypedExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
ICallRequest command, ICancellationRepository cancellationRepository, ICallRequest command, ICancellationRepository cancellationRepository,
IRepresentationModule representationModule) IRepresentationModule representationModule)
{ {
@@ -147,6 +176,8 @@ namespace mROA.Implementation.Backend
CommandId = command.CommandId, CommandId = command.CommandId,
Type = finalResult?.GetType() Type = finalResult?.GetType()
}; };
_cancellationRepo.FreeCancelation(command.Id);
var multiClientOwnershipRepository = var multiClientOwnershipRepository =
TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository; TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository;
multiClientOwnershipRepository?.RegisterOwnership(representationModule.Id); multiClientOwnershipRepository?.RegisterOwnership(representationModule.Id);
+11 -1
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
// ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
@@ -18,9 +19,18 @@ namespace mROA.Implementation
public Guid Id { get; set; } = Guid.NewGuid(); public Guid Id { get; set; } = Guid.NewGuid();
public int CommandId { get; set; } public int CommandId { get; set; }
public int ObjectId { get; set; } = -1; public int ObjectId { get; set; } = -1;
[JsonIgnore] [JsonIgnore]
public Type? ParameterType { get; set; } public Type? ParameterType { get; set; }
public object? Parameter { get; set; } public object? Parameter { get; set; }
} }
public class CancelRequest : ICallRequest
{
public Guid Id { get; set; }
public int CommandId { get; set; } = -2;
public int ObjectId { get; set; } = -2;
public object? Parameter { get; set; } = null;
}
} }
@@ -1,5 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using mROA.Abstract; using mROA.Abstract;
using mROA.Implementation.Backend; using mROA.Implementation.Backend;
@@ -53,45 +54,68 @@ namespace mROA.Implementation.Frontend
throw new NullReferenceException("Method repository is null."); throw new NullReferenceException("Method repository is null.");
await Task.Yield(); await Task.Yield();
var multiClientOwnershipRepository = TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository; var multiClientOwnershipRepository =
TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository;
multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id); multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id);
try try
{ {
while (true) while (true)
{ {
var request = Console.WriteLine("Waiting for request...");
_representationModule!.GetMessage<DefaultCallRequest>(messageType: MessageType.CallRequest); var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var defaultRequest =
_representationModule!.GetMessageAsync<DefaultCallRequest>(
messageType: MessageType.CallRequest, token: token);
var cancelRequest =
_representationModule!.GetMessageAsync<CancelRequest>(
messageType: MessageType.CancelRequest, token: token);
// Console.WriteLine("Executing {0}", request.Id); Task.WaitAny(defaultRequest, cancelRequest);
if (request.Parameter is not null) Console.WriteLine("Request received");
if (cancelRequest.IsCompleted)
{ {
var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First() Console.WriteLine("Cancelling request");
.ParameterType; var req = cancelRequest.Result;
tokenSource.Cancel();
request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType); _executeModule.Execute(req, _contextRepository, _representationModule);
} }
else
var result = _executeModule.Execute(request, _contextRepository, _representationModule);
var resultType = MessageType.Unknown;
switch (result)
{ {
case FinalCommandExecution: tokenSource.Cancel();
resultType = MessageType.FinishedCommandExecution; var request = defaultRequest.Result;
break;
case AsyncCommandExecution:
resultType = MessageType.AsyncCommandExecution;
break;
case ExceptionCommandExecution:
resultType = MessageType.ExceptionCommandExecution;
break;
}
_representationModule.PostCallMessage(request.Id, resultType, result, result.GetType()); if (request.Parameter is not null)
{
var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First()
.ParameterType;
request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType);
}
var result = _executeModule.Execute(request, _contextRepository, _representationModule);
var resultType = MessageType.Unknown;
switch (result)
{
case FinalCommandExecution:
resultType = MessageType.FinishedCommandExecution;
break;
case AsyncCommandExecution:
resultType = MessageType.AsyncCommandExecution;
break;
case ExceptionCommandExecution:
resultType = MessageType.ExceptionCommandExecution;
break;
}
_representationModule.PostCallMessage(request.Id, resultType, result, result.GetType());
}
} }
} }
catch catch
@@ -99,6 +123,5 @@ namespace mROA.Implementation.Frontend
multiClientOwnershipRepository?.FreeOwnership(); multiClientOwnershipRepository?.FreeOwnership();
} }
} }
} }
} }
@@ -86,10 +86,11 @@ namespace mROA.Implementation
// Console.WriteLine("Receiving {0}", Encoding.Default.GetString(_buffer[..len])); // Console.WriteLine("Receiving {0}", Encoding.Default.GetString(_buffer[..len]));
var message = _serialization.Deserialize<NetworkMessage>(localSpan.Span); var message = _serialization.Deserialize<NetworkMessage>(localSpan.Span);
_messageBuffer.Add(message!); Console.WriteLine($"Received Message {message.SchemaId} - {message.Id}");
_messageBuffer.Add(message);
_currentReceiving = Task.Run(async () => await GetNextMessage()); _currentReceiving = Task.Run(async () => await GetNextMessage());
return message!; return message;
} }
} }
} }
+33 -10
View File
@@ -1,4 +1,5 @@
using System.Threading; using System;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using mROA.Abstract; using mROA.Abstract;
using mROA.Implementation.CommandExecution; using mROA.Implementation.CommandExecution;
@@ -7,7 +8,7 @@ using mROA.Implementation.CommandExecution;
namespace mROA.Implementation namespace mROA.Implementation
{ {
public abstract class RemoteObjectBase public abstract class RemoteObjectBase : IDisposable
{ {
private readonly int _id; private readonly int _id;
private readonly IRepresentationModule _representationModule; private readonly IRepresentationModule _representationModule;
@@ -20,7 +21,7 @@ namespace mROA.Implementation
public int Id => _id; public int Id => _id;
public int OwnerId => _representationModule.Id; public int OwnerId => _representationModule.Id;
protected async Task<T> GetResultAsync<T>(int methodId, object? parameter = default, protected async Task<T> GetResultAsync<T>(int methodId, object? parameter = default,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@@ -46,6 +47,7 @@ namespace mROA.Implementation
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
await _representationModule.PostCallMessageAsync(request.Id, MessageType.CancelRequest, request.Id); await _representationModule.PostCallMessageAsync(request.Id, MessageType.CancelRequest, request.Id);
localTokenSource.Cancel();
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
} }
@@ -76,21 +78,42 @@ namespace mROA.Implementation
_representationModule.GetMessageAsync<ExceptionCommandExecution>(requestId: request.Id, _representationModule.GetMessageAsync<ExceptionCommandExecution>(requestId: request.Id,
MessageType.ExceptionCommandExecution, localTokenSource.Token); MessageType.ExceptionCommandExecution, localTokenSource.Token);
cancellationToken.Register(async () =>
{
Console.WriteLine("Cancelling task");
await _representationModule.PostCallMessageAsync(request.Id, MessageType.CancelRequest,
new CancelRequest
{
Id = request.Id
});
localTokenSource.Cancel();
});
Task.WaitAny(new Task[] Task.WaitAny(new Task[]
{ {
successResponse, errorResponse errorResponse, successResponse
}, cancellationToken); }, cancellationToken);
if (cancellationToken.IsCancellationRequested) Console.WriteLine($"Handling message");
{
await _representationModule.PostCallMessageAsync(request.Id, MessageType.CancelRequest, request.Id); // if (cancellationToken.IsCancellationRequested)
cancellationToken.ThrowIfCancellationRequested(); // {
} // localTokenSource.Cancel();
// return;
// }
if (successResponse.IsCompletedSuccessfully) if (successResponse.IsCompletedSuccessfully)
return; return;
throw errorResponse.Result.GetException(); if (errorResponse.IsCompletedSuccessfully)
throw errorResponse.Result.GetException();
}
public void Dispose()
{
if (_id == -1)
return;
CallAsync(-1).Wait();
} }
} }
} }
+5 -2
View File
@@ -57,7 +57,8 @@ namespace mROA.Implementation
{ {
var message = await _interaction.GetNextMessageReceiving(); var message = await _interaction.GetNextMessageReceiving();
if ((requestId is not null && message.Id != requestId) || if ((requestId is not null && message.Id != requestId) ||
(messageType is not null && message.SchemaId != messageType)) continue; (messageType is not null && message.SchemaId != messageType))
continue;
_interaction.HandleMessage(message); _interaction.HandleMessage(message);
return message.Data; return message.Data;
@@ -79,7 +80,9 @@ namespace mROA.Implementation
throw new NullReferenceException("Interaction toolkit is not initialized"); throw new NullReferenceException("Interaction toolkit is not initialized");
if (_serialization == null) if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is not initialized"); throw new NullReferenceException("Serialization toolkit is not initialized");
Console.WriteLine($"Posting message: {id} - {messageType}");
await _interaction.PostMessage(new NetworkMessage await _interaction.PostMessage(new NetworkMessage
{ Id = id, SchemaId = messageType, Data = _serialization.Serialize(payload, payloadType) }); { Id = id, SchemaId = messageType, Data = _serialization.Serialize(payload, payloadType) });
} }