110,535
社区成员
发帖
与我相关
我的任务
分享
class 有个问题
{
Task 任务发送; // 同一时间只能被调用一次
public async void 命令发送(string 命令)
{
任务发送 = ClientWebSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(命令)), WebSocketMessageType.Text, true, new CancellationToken());
await 任务发送;
}
}
因为Task 任务发送不可以被多个线程同时调用,所以,我要写一个可以被多线程同时调用的方法,去应对并发。请问这要怎么处理,将并发改为一个一个处理的任务?
static void Main(string[] args)
{
//add task item
var taskItems = new BlockingCollection<string>();
Task.Run(async () =>
{
var guid = Guid.NewGuid().ToString();
taskItems.TryAdd(guid);
//add some delay time
await Task.Delay(Math.Abs(guid.GetHashCode())%5000);
});
//consume item
Task.Run(async () =>
{
foreach(var item in taskItems.GetConsumingEnumerable())
{
await Task.Run(() =>
{
//ClientWebSocket.SendAsync
});
}
});
Console.Read();
}
private async Task SendAsyncCore(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
{
string inputParameter = string.Empty;
if (s_LoggingEnabled)
{
inputParameter = string.Format(CultureInfo.InvariantCulture, "messageType: {0}, endOfMessage: {1}", new object[2] { messageType, endOfMessage });
Logging.Enter(Logging.WebSockets, this, "SendAsync", inputParameter);
}
try
{
ThrowIfPendingException();
ThrowIfDisposed();
WebSocket.ThrowOnInvalidState(State, WebSocketState.Open, WebSocketState.CloseReceived);
bool ownsCancellationTokenSource = false;
CancellationToken linkedCancellationToken = CancellationToken.None;
try
{
while (true)
{
bool flag;
ownsCancellationTokenSource = (flag = m_SendOutstandingOperationHelper.TryStartOperation(cancellationToken, out linkedCancellationToken));
if (flag)
{
break;
}
Task keepAliveTask;
lock (SessionHandle)
{
keepAliveTask = m_KeepAliveTask;
if (keepAliveTask == null)
{
m_SendOutstandingOperationHelper.CompleteOperation(ownsCancellationTokenSource);
ownsCancellationTokenSource = (flag = m_SendOutstandingOperationHelper.TryStartOperation(cancellationToken, out linkedCancellationToken));
if (flag)
{
break;
}
throw new InvalidOperationException(SR.GetString("net_Websockets_AlreadyOneOutstandingOperation", "SendAsync"));
}
}
await keepAliveTask.SuppressContextFlow();
ThrowIfPendingException();
m_SendOutstandingOperationHelper.CompleteOperation(ownsCancellationTokenSource);
}
if (s_LoggingEnabled && buffer.Count > 0)
{
Logging.Dump(Logging.WebSockets, this, "SendAsync", buffer.Array, buffer.Offset, buffer.Count);
}
_ = buffer.Offset;
EnsureSendOperation();
m_SendOperation.BufferType = GetBufferType(messageType, endOfMessage);
await m_SendOperation.Process(buffer, linkedCancellationToken).SuppressContextFlow();
}
catch (Exception exception)
{
bool isCancellationRequested = linkedCancellationToken.IsCancellationRequested;
Abort();
ThrowIfConvertibleException("SendAsync", exception, cancellationToken, isCancellationRequested);
throw;
}
finally
{
m_SendOutstandingOperationHelper.CompleteOperation(ownsCancellationTokenSource);
}
}
finally
{
if (s_LoggingEnabled)
{
Logging.Exit(Logging.WebSockets, this, "SendAsync", inputParameter);
}
}
}
你可以看到他内部是加锁的,同时一个关键核心
public bool TryStartOperation(CancellationToken userCancellationToken, out CancellationToken linkedCancellationToken)
{
linkedCancellationToken = CancellationToken.None;
ThrowIfDisposed();
lock (m_ThisLock)
{
if (++m_OperationsOutstanding == 1)
{
linkedCancellationToken = CreateLinkedCancellationToken(userCancellationToken);
return true;
}
return false;
}
}
public void CompleteOperation(bool ownsCancellationTokenSource)
{
if (m_IsDisposed)
{
return;
}
CancellationTokenSource cancellationTokenSource = null;
lock (m_ThisLock)
{
m_OperationsOutstanding--;
if (ownsCancellationTokenSource)
{
cancellationTokenSource = m_CancellationTokenSource;
m_CancellationTokenSource = null;
}
}
cancellationTokenSource?.Dispose();
}
依旧还是加锁的,并且m_OperationsOutstanding这玩意其实就是一个信号量控制