mirror of
https://github.com/DarthAffe/OBD.NET.git
synced 2025-12-12 08:48:30 +00:00
Fixed uses of nullable reference types
This commit is contained in:
parent
18b0fec0f2
commit
163f5eb3a3
@ -21,9 +21,7 @@ public class Program
|
||||
Console.WriteLine("\nAvailable ports:");
|
||||
|
||||
foreach (string port in availablePorts)
|
||||
{
|
||||
Console.WriteLine(port);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -33,10 +31,10 @@ public class Program
|
||||
using SerialConnection connection = new(comPort);
|
||||
using ELM327 dev = new(connection, new OBDConsoleLogger(OBDLogLevel.Debug));
|
||||
|
||||
dev.SubscribeDataReceived<EngineRPM>((sender, data) => Console.WriteLine("EngineRPM: " + data.Data.Rpm));
|
||||
dev.SubscribeDataReceived<EngineFuelRate>((sender, data) => Console.WriteLine("VehicleSpeed: " + data.Data));
|
||||
dev.SubscribeDataReceived<EngineRPM>((_, data) => Console.WriteLine("EngineRPM: " + data.Data.Rpm));
|
||||
dev.SubscribeDataReceived<EngineFuelRate>((_, data) => Console.WriteLine("VehicleSpeed: " + data.Data));
|
||||
|
||||
dev.SubscribeDataReceived<IOBDData>((sender, data) => Console.WriteLine($"PID {data.Data.PID.ToHexString()}: {data.Data}"));
|
||||
dev.SubscribeDataReceived<IOBDData>((_, data) => Console.WriteLine($"PID {data.Data.PID.ToHexString()}: {data.Data}"));
|
||||
|
||||
dev.Initialize();
|
||||
dev.RequestData<FuelType>();
|
||||
@ -66,18 +64,18 @@ public class Program
|
||||
using SerialConnection connection = new(comPort);
|
||||
using ELM327 dev = new(connection, new OBDConsoleLogger(OBDLogLevel.Debug));
|
||||
|
||||
dev.Initialize();
|
||||
await dev.InitializeAsync();
|
||||
|
||||
EngineRPM engineRpm = await dev.RequestDataAsync<EngineRPM>();
|
||||
Console.WriteLine("Data: " + engineRpm.Rpm);
|
||||
EngineRPM? engineRpm = await dev.RequestDataAsync<EngineRPM>();
|
||||
Console.WriteLine("Data: " + (engineRpm?.Rpm.ToString() ?? "-"));
|
||||
|
||||
engineRpm = await dev.RequestDataAsync<EngineRPM>();
|
||||
Console.WriteLine("Data: " + engineRpm.Rpm);
|
||||
Console.WriteLine("Data: " + (engineRpm?.Rpm.ToString() ?? "-"));
|
||||
|
||||
VehicleSpeed vehicleSpeed = await dev.RequestDataAsync<VehicleSpeed>();
|
||||
Console.WriteLine("Data: " + vehicleSpeed.Speed);
|
||||
VehicleSpeed? vehicleSpeed = await dev.RequestDataAsync<VehicleSpeed>();
|
||||
Console.WriteLine("Data: " + (vehicleSpeed?.Speed.ToString() ?? "-"));
|
||||
|
||||
engineRpm = await dev.RequestDataAsync<EngineRPM>();
|
||||
Console.WriteLine("Data: " + engineRpm.Rpm);
|
||||
Console.WriteLine("Data: " + (engineRpm?.Rpm.ToString() ?? "-"));
|
||||
}
|
||||
}
|
||||
@ -46,7 +46,6 @@ namespace OBD.NET.Communication
|
||||
/// Initializes a new instance of the <see cref="BluetoothSerialConnection"/> class.
|
||||
/// </summary>
|
||||
/// <param name="deviceName">Name of the _device.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public BluetoothSerialConnection(string deviceName)
|
||||
{
|
||||
this._device = deviceName;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
@ -28,13 +28,13 @@ public class ATCommand
|
||||
#region Properties & Fields
|
||||
|
||||
public string Command { get; }
|
||||
public string ExpectedResult { get; }
|
||||
public string? ExpectedResult { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
private ATCommand(string command, string expectedResult = null)
|
||||
private ATCommand(string command, string? expectedResult = null)
|
||||
{
|
||||
this.Command = command;
|
||||
this.ExpectedResult = expectedResult;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#if NET5_0_OR_GREATER
|
||||
|
||||
using System.IO.Ports;
|
||||
using System.Text;
|
||||
using OBD.NET.Communication.EventArgs;
|
||||
|
||||
namespace OBD.NET.Communication;
|
||||
@ -12,19 +11,16 @@ public class SerialConnection : ISerialConnection
|
||||
|
||||
private readonly SerialPort _serialPort;
|
||||
|
||||
public bool IsOpen => _serialPort?.IsOpen ?? false;
|
||||
public bool IsOpen => _serialPort.IsOpen;
|
||||
public bool IsAsync => false;
|
||||
|
||||
private readonly byte[] _readBuffer = new byte[1024];
|
||||
private readonly StringBuilder _lineBuffer = new();
|
||||
|
||||
private readonly AutoResetEvent _hasPrompt = new(true);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler<DataReceivedEventArgs> DataReceived = delegate { };
|
||||
public event EventHandler<DataReceivedEventArgs>? DataReceived = delegate { };
|
||||
|
||||
#endregion
|
||||
|
||||
@ -61,7 +57,7 @@ public class SerialConnection : ISerialConnection
|
||||
DataReceived?.Invoke(this, new DataReceivedEventArgs(count, _readBuffer));
|
||||
}
|
||||
|
||||
public void Dispose() => _serialPort?.Dispose();
|
||||
public void Dispose() => _serialPort.Dispose();
|
||||
|
||||
public Task ConnectAsync() => throw new NotSupportedException("Asynchronous operations not supported");
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ public class Count : GenericData
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
protected override string Unit => null;
|
||||
protected override string? Unit => null;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ public class Degree : GenericData
|
||||
|
||||
#region Methods
|
||||
|
||||
public override string ToString() => (IsFloatingPointValue ? Value.ToString("0.00") : Value.ToString()) + (Unit ?? string.Empty);
|
||||
public override string ToString() => (IsFloatingPointValue ? Value.ToString("0.00") : Value.ToString()) + Unit;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -22,7 +22,7 @@ public class DegreeCelsius : GenericData
|
||||
|
||||
#region Methods
|
||||
|
||||
public override string ToString() => (IsFloatingPointValue ? Value.ToString("0.00") : Value.ToString()) + (Unit ?? string.Empty);
|
||||
public override string ToString() => (IsFloatingPointValue ? Value.ToString("0.00") : Value.ToString()) + Unit;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -9,7 +9,7 @@ public abstract class GenericData
|
||||
public double MaxValue { get; }
|
||||
public bool IsFloatingPointValue { get; }
|
||||
|
||||
protected abstract string Unit { get; }
|
||||
protected abstract string? Unit { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ public class Ratio : GenericData
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
protected override string Unit => null;
|
||||
protected override string? Unit => null;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ public class CommandResult
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public object Result { get; set; }
|
||||
public object? Result { get; set; }
|
||||
public AsyncManualResetEvent WaitHandle { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
@ -21,7 +21,7 @@ public class ELM327 : SerialDevice
|
||||
|
||||
protected Mode Mode { get; set; } = Mode.ShowCurrentData; //TODO DarthAffe 26.06.2016: Implement different modes
|
||||
|
||||
protected string MessageChunk { get; set; }
|
||||
protected string MessageChunk { get; set; } = string.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -30,13 +30,13 @@ public class ELM327 : SerialDevice
|
||||
public delegate void DataReceivedEventHandler<T>(object sender, DataReceivedEventArgs<T> args) where T : IOBDData;
|
||||
|
||||
public delegate void RawDataReceivedEventHandler(object sender, RawDataReceivedEventArgs args);
|
||||
public event RawDataReceivedEventHandler RawDataReceived;
|
||||
public event RawDataReceivedEventHandler? RawDataReceived;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ELM327(ISerialConnection connection, IOBDLogger logger = null)
|
||||
public ELM327(ISerialConnection connection, IOBDLogger? logger = null)
|
||||
: base(connection, logger: logger)
|
||||
{ }
|
||||
|
||||
@ -124,7 +124,7 @@ public class ELM327 : SerialDevice
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<T> RequestDataAsync<T>()
|
||||
public virtual async Task<T?> RequestDataAsync<T>()
|
||||
where T : class, IOBDData, new()
|
||||
{
|
||||
Logger?.WriteLine("Requesting Type " + typeof(T).Name + " ...", OBDLogLevel.Debug);
|
||||
@ -135,9 +135,8 @@ public class ELM327 : SerialDevice
|
||||
/// <summary>
|
||||
/// Requests the data asynchronous and return the data when available
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IOBDData> RequestDataAsync(Type type)
|
||||
public virtual async Task<IOBDData?> RequestDataAsync(Type type)
|
||||
{
|
||||
Logger?.WriteLine("Requesting Type " + type.Name + " ...", OBDLogLevel.Debug);
|
||||
byte pid = ResolvePid(type);
|
||||
@ -148,7 +147,7 @@ public class ELM327 : SerialDevice
|
||||
/// Request data based on a pid
|
||||
/// </summary>
|
||||
/// <param name="pid">The pid of the requested data</param>
|
||||
public virtual async Task<object> RequestDataAsync(byte pid)
|
||||
public virtual async Task<object?> RequestDataAsync(byte pid)
|
||||
{
|
||||
Logger?.WriteLine("Requesting PID " + pid.ToString("X2") + " ...", OBDLogLevel.Debug);
|
||||
CommandResult result = SendCommand(((byte)Mode).ToString("X2") + pid.ToString("X2"));
|
||||
@ -157,10 +156,8 @@ public class ELM327 : SerialDevice
|
||||
return result.Result;
|
||||
}
|
||||
|
||||
protected override object ProcessMessage(string message)
|
||||
protected override object? ProcessMessage(string message)
|
||||
{
|
||||
if (message == null) return null;
|
||||
|
||||
DateTime timestamp = DateTime.Now;
|
||||
|
||||
RawDataReceived?.Invoke(this, new RawDataReceivedEventArgs(message, timestamp));
|
||||
@ -177,7 +174,7 @@ public class ELM327 : SerialDevice
|
||||
else if (message[0] == '1')
|
||||
{
|
||||
string fullMessage = MessageChunk + message.Substring(2, message.Length - 2);
|
||||
MessageChunk = null;
|
||||
MessageChunk = string.Empty;
|
||||
return ProcessMessage(fullMessage);
|
||||
}
|
||||
}
|
||||
@ -187,15 +184,15 @@ public class ELM327 : SerialDevice
|
||||
if (mode == (byte)Mode)
|
||||
{
|
||||
byte pid = (byte)message.Substring(2, 2).GetHexVal();
|
||||
if (DataTypeCache.TryGetValue(pid, out Type dataType))
|
||||
if (DataTypeCache.TryGetValue(pid, out Type? dataType))
|
||||
{
|
||||
IOBDData obdData = (IOBDData)Activator.CreateInstance(dataType);
|
||||
IOBDData obdData = (IOBDData)Activator.CreateInstance(dataType)!;
|
||||
obdData.Load(message.Substring(4, message.Length - 4));
|
||||
|
||||
if (DataReceivedEventHandlers.TryGetValue(dataType, out IDataEventManager dataEventManager))
|
||||
if (DataReceivedEventHandlers.TryGetValue(dataType, out IDataEventManager? dataEventManager))
|
||||
dataEventManager.RaiseEvent(this, obdData, timestamp);
|
||||
|
||||
if (DataReceivedEventHandlers.TryGetValue(typeof(IOBDData), out IDataEventManager genericDataEventManager))
|
||||
if (DataReceivedEventHandlers.TryGetValue(typeof(IOBDData), out IDataEventManager? genericDataEventManager))
|
||||
genericDataEventManager.RaiseEvent(this, obdData, timestamp);
|
||||
|
||||
return obdData;
|
||||
@ -223,8 +220,7 @@ public class ELM327 : SerialDevice
|
||||
|
||||
protected virtual byte AddToPidCache(Type obdDataType)
|
||||
{
|
||||
IOBDData data = (IOBDData)Activator.CreateInstance(obdDataType);
|
||||
if (data == null) throw new ArgumentException("Has to implement IOBDData", nameof(obdDataType));
|
||||
if (Activator.CreateInstance(obdDataType) is not IOBDData data) throw new ArgumentException("Has to implement IOBDData", nameof(obdDataType));
|
||||
|
||||
byte pid = data.PID;
|
||||
|
||||
@ -267,7 +263,7 @@ public class ELM327 : SerialDevice
|
||||
|
||||
public void SubscribeDataReceived<T>(DataReceivedEventHandler<T> eventHandler) where T : IOBDData
|
||||
{
|
||||
if (!DataReceivedEventHandlers.TryGetValue(typeof(T), out IDataEventManager eventManager))
|
||||
if (!DataReceivedEventHandlers.TryGetValue(typeof(T), out IDataEventManager? eventManager))
|
||||
DataReceivedEventHandlers.Add(typeof(T), (eventManager = new GenericDataEventManager<T>()));
|
||||
|
||||
((GenericDataEventManager<T>)eventManager).DataReceived += eventHandler;
|
||||
@ -275,7 +271,7 @@ public class ELM327 : SerialDevice
|
||||
|
||||
public void UnsubscribeDataReceived<T>(DataReceivedEventHandler<T> eventHandler) where T : IOBDData
|
||||
{
|
||||
if (DataReceivedEventHandlers.TryGetValue(typeof(T), out IDataEventManager eventManager))
|
||||
if (DataReceivedEventHandlers.TryGetValue(typeof(T), out IDataEventManager? eventManager))
|
||||
((GenericDataEventManager<T>)eventManager).DataReceived -= eventHandler;
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ public class STN1170 : ELM327 // Fully compatible device
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public STN1170(ISerialConnection connection, IOBDLogger logger = null)
|
||||
public STN1170(ISerialConnection connection, IOBDLogger? logger = null)
|
||||
: base(connection, logger)
|
||||
{ }
|
||||
|
||||
|
||||
@ -17,16 +17,16 @@ public abstract class SerialDevice : IDisposable
|
||||
private readonly BlockingCollection<QueuedCommand> _commandQueue = new();
|
||||
private readonly StringBuilder _lineBuffer = new();
|
||||
private readonly AutoResetEvent _commandFinishedEvent = new(false);
|
||||
private Task _commandWorkerTask;
|
||||
private CancellationTokenSource _commandCancellationToken;
|
||||
private Task? _commandWorkerTask;
|
||||
private CancellationTokenSource? _commandCancellationToken;
|
||||
|
||||
private volatile int _queueSize = 0;
|
||||
private readonly ManualResetEvent _queueEmptyEvent = new(true);
|
||||
|
||||
public int QueueSize => _queueSize;
|
||||
|
||||
protected QueuedCommand CurrentCommand;
|
||||
protected IOBDLogger Logger { get; }
|
||||
protected QueuedCommand? CurrentCommand;
|
||||
protected IOBDLogger? Logger { get; }
|
||||
protected ISerialConnection Connection { get; }
|
||||
protected char Terminator { get; set; }
|
||||
|
||||
@ -40,7 +40,7 @@ public abstract class SerialDevice : IDisposable
|
||||
/// <param name="connection">connection.</param>
|
||||
/// <param name="terminator">terminator used for terminating the command message</param>
|
||||
/// <param name="logger">logger instance</param>
|
||||
protected SerialDevice(ISerialConnection connection, char terminator = '\r', IOBDLogger logger = null)
|
||||
protected SerialDevice(ISerialConnection connection, char terminator = '\r', IOBDLogger? logger = null)
|
||||
{
|
||||
this.Connection = connection;
|
||||
this.Terminator = terminator;
|
||||
@ -88,8 +88,7 @@ public abstract class SerialDevice : IDisposable
|
||||
_commandCancellationToken = new CancellationTokenSource();
|
||||
_commandWorkerTask = Task.Factory.StartNew(CommandWorker);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends the command.
|
||||
/// </summary>
|
||||
@ -105,7 +104,7 @@ public abstract class SerialDevice : IDisposable
|
||||
|
||||
QueuedCommand cmd = new(command);
|
||||
_queueEmptyEvent.Reset();
|
||||
_queueSize++;
|
||||
Interlocked.Increment(ref _queueSize);
|
||||
_commandQueue.Add(cmd);
|
||||
|
||||
return cmd.CommandResult;
|
||||
@ -131,7 +130,7 @@ public abstract class SerialDevice : IDisposable
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="DataReceivedEventArgs"/> instance containing the event data.</param>
|
||||
private void OnDataReceived(object sender, DataReceivedEventArgs e)
|
||||
private void OnDataReceived(object? sender, DataReceivedEventArgs e)
|
||||
{
|
||||
for (int i = 0; i < e.Count; i++)
|
||||
{
|
||||
@ -143,7 +142,7 @@ public abstract class SerialDevice : IDisposable
|
||||
break;
|
||||
|
||||
case '>':
|
||||
CurrentCommand.CommandResult.WaitHandle.Set();
|
||||
CurrentCommand?.CommandResult.WaitHandle.Set();
|
||||
_commandFinishedEvent.Set();
|
||||
break;
|
||||
|
||||
@ -178,8 +177,9 @@ public abstract class SerialDevice : IDisposable
|
||||
/// <param name="message">The message.</param>
|
||||
private void InternalProcessMessage(string message)
|
||||
{
|
||||
object data = ProcessMessage(message);
|
||||
CurrentCommand.CommandResult.Result = data;
|
||||
object? data = ProcessMessage(message);
|
||||
if (CurrentCommand != null)
|
||||
CurrentCommand.CommandResult.Result = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -187,13 +187,15 @@ public abstract class SerialDevice : IDisposable
|
||||
/// </summary>
|
||||
/// <param name="message">message received</param>
|
||||
/// <returns>result data</returns>
|
||||
protected abstract object ProcessMessage(string message);
|
||||
protected abstract object? ProcessMessage(string message);
|
||||
|
||||
/// <summary>
|
||||
/// Worker method for sending commands
|
||||
/// </summary>
|
||||
private async void CommandWorker()
|
||||
{
|
||||
if (_commandCancellationToken == null) return;
|
||||
|
||||
CancellationToken cancellationToken = _commandCancellationToken.Token;
|
||||
|
||||
while (!_commandCancellationToken.IsCancellationRequested)
|
||||
@ -207,13 +209,14 @@ public abstract class SerialDevice : IDisposable
|
||||
{
|
||||
if (_commandQueue.TryTake(out CurrentCommand, 10, cancellationToken))
|
||||
{
|
||||
_queueSize--;
|
||||
Interlocked.Decrement(ref _queueSize);
|
||||
|
||||
Logger?.WriteLine("Writing Command: '" + CurrentCommand.CommandText.Replace('\r', '\'') + "'", OBDLogLevel.Verbose);
|
||||
|
||||
if (Connection.IsAsync)
|
||||
await Connection.WriteAsync(Encoding.ASCII.GetBytes(CurrentCommand.CommandText));
|
||||
else
|
||||
// ReSharper disable once MethodHasAsyncOverload
|
||||
Connection.Write(Encoding.ASCII.GetBytes(CurrentCommand.CommandText));
|
||||
|
||||
// wait for command to finish or command canceled
|
||||
@ -233,7 +236,7 @@ public abstract class SerialDevice : IDisposable
|
||||
|
||||
public void WaitQueue() => _queueEmptyEvent.WaitOne();
|
||||
|
||||
public async Task WaitQueueAsync() => await Task.Run(() => WaitQueue());
|
||||
public async Task WaitQueueAsync() => await Task.Run(WaitQueue);
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
@ -243,7 +246,7 @@ public abstract class SerialDevice : IDisposable
|
||||
_commandQueue.CompleteAdding();
|
||||
_commandCancellationToken?.Cancel();
|
||||
_commandWorkerTask?.Wait();
|
||||
Connection?.Dispose();
|
||||
Connection.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -9,7 +9,7 @@ public class GenericDataEventManager<T> : IDataEventManager
|
||||
{
|
||||
#region Events
|
||||
|
||||
internal event ELM327.DataReceivedEventHandler<T> DataReceived;
|
||||
internal event ELM327.DataReceivedEventHandler<T>? DataReceived;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ public class CalculatedEngineLoad : AbstractOBDData
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public Percent Load => new(A / 2.55, 0, 100);
|
||||
public new Percent Load => new(A / 2.55, 0, 100);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ public class AbsoluteLoadValue : AbstractOBDData
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public Percent Load => new(((256 * A) + B) / 2.55, 0, 25700);
|
||||
public new Percent Load => new(((256 * A) + B) / 2.55, 0, 25700);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ public abstract class AbstractOBDData : IOBDData
|
||||
public byte PID { get; }
|
||||
private readonly int _length;
|
||||
|
||||
private byte[] _rawData;
|
||||
private byte[] _rawData = Array.Empty<byte>();
|
||||
public byte[] RawData
|
||||
{
|
||||
get => _rawData;
|
||||
|
||||
@ -26,8 +26,8 @@ public class AsyncManualResetEvent
|
||||
public void Set()
|
||||
{
|
||||
TaskCompletionSource<bool> tcs = _tcs;
|
||||
Task.Factory.StartNew(s => ((TaskCompletionSource<bool>)s).TrySetResult(true),
|
||||
tcs, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default);
|
||||
Task.Factory.StartNew(s => ((TaskCompletionSource<bool>)s!).TrySetResult(true),
|
||||
tcs, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default);
|
||||
|
||||
tcs.Task.Wait();
|
||||
}
|
||||
@ -40,8 +40,7 @@ public class AsyncManualResetEvent
|
||||
while (true)
|
||||
{
|
||||
TaskCompletionSource<bool> tcs = _tcs;
|
||||
if (!tcs.Task.IsCompleted ||
|
||||
(Interlocked.CompareExchange(ref _tcs, new TaskCompletionSource<bool>(), tcs) == tcs))
|
||||
if (!tcs.Task.IsCompleted || (Interlocked.CompareExchange(ref _tcs, new TaskCompletionSource<bool>(), tcs) == tcs))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user