多线程中的c#数据处理不正确
我有一个产品下拉列表,选择产品连接到websocket并获取该产品的提要消息。一旦(1)feed消息开始出现,我必须(2)获取订单簿,然后(3)处理feed消息。因此,第一个和最后一个任务将异步运行。为此,我编写了以下代码:多线程中的c#数据处理不正确,c#,multithreading,winforms,C#,Multithreading,Winforms,我有一个产品下拉列表,选择产品连接到websocket并获取该产品的提要消息。一旦(1)feed消息开始出现,我必须(2)获取订单簿,然后(3)处理feed消息。因此,第一个和最后一个任务将异步运行。为此,我编写了以下代码: void OnReceivingFeedMessage() { concurrentQueue.Enqueue(message); if (!messageStreamStarted) // only first time get order bo
void OnReceivingFeedMessage()
{
concurrentQueue.Enqueue(message);
if (!messageStreamStarted) // only first time get order book
{
messageStreamStarted = true;
GetOrderBookData();
}
}
private void GetOrderBookData()
{
MarketData m = new MarketData();
ProductOrderBook p = m.GetProductOrderBook(productId);
bidsList = p.bids;
asksList = p.asks;
isOrderBookUpdated = true;
Task task3 = Task.Run(() => KickStartToProcessQueue());
}
private void KickStartToProcessQueue()
{
while (threadProcessQueueExist)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
if (isOrderBookUpdated)
{
ProcessQueueMessages();
}
}
}
}
private void ProcessQueueMessages()
{
if (!concurrentQueue.IsEmpty)
{
string jsonString;
while (concurrentQueue.TryDequeue(out jsonString))
{
// have to insert the record in existing order book
}
}
}
这是第一次完美地工作。但是,当我更换产品并重新连接时,事情变得一团糟,数据处理不当。写在product selectedindex上的代码会发生更改
private void CloseAndReconnectToGetWebsocketFeed()
{
w.CloseWebsocketConnection();
messageStreamStarted = false;
isOrderBookUpdated = false;
ConcurrentQueue<string> wssMessagesQueue = new ConcurrentQueue<string>();
concurrentQueue = wssMessagesQueue;
ConnectAndGetWebsocketFeedMessages(); // this calls OnReceivingFeedMessage
}
private void closeandconnecttogetWebsocketfeed()
{
w、 CloseWebsocketConnection();
messageStreamStarted=false;
isOrderBookUpdated=false;
ConcurrentQueue wssMessagesQueue=新ConcurrentQueue();
concurrentQueue=wssMessagesQueue;
ConnectAndGetWebsocketFeedMessages();//这将调用ReceivingFeedMessage
}
我是多线程新手,所以不确定是否需要使用lock、async/await或其他方法。在上面的代码中我做错了什么
第一次运行时运行良好,但当我更换产品并再次执行相同的处理时,它开始出现问题。有人能告诉我,在一遍又一遍地执行相同的步骤之前,我如何清除所有的资源吗?我认为您正在编写不必要的复杂代码。我不是100%确定,你的问题是什么,但这里有一些东西可能会帮助你 使用
BlockingCollection
使用该类,您可以停止您的消费者线程,直到收到新消息。下面是一个简单的例子,说明这些东西是如何工作的:
BlockingCollection<string> collection = new BlockingCollection<string>(new ConcurrentQueue<string>());
Task t = Task.Run(() =>
{
while (collection.TryTake(out string item, Timeout.Infinite))
{
Console.WriteLine($"Started reading {item}...");
Thread.Sleep(1000); //simulate intense work
Console.WriteLine($"Done reading {item}");
}
});
while (true)
{
//This could be your OnReceivingFeedMessage()
string input = Console.ReadLine();
if (input == "stop")
{
Console.WriteLine("Stopping...");
collection.CompleteAdding();
break;
}
else
{
collection.Add(input);
}
}
t.Wait();
这还有一个优点(或缺点),即任务都是并行运行的。这意味着你不能依赖于他们的工作顺序,但他们会处理得更快
顺便说一句:这两种方法都有一个优点,那就是你不用忙着等待。根据你的问题:
while (threadProcessQueueExist)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
if (isOrderBookUpdated)
{
ProcessQueueMessages();
}
}
}
只要队列中没有任何内容,这段代码就会创建忙等待,这意味着处理器的一个核心将处于非常高的负载,而实际上什么也不做。这被认为是一种不好的做法。您的代码似乎过于复杂。我的理解是否正确,您希望在消息传入时立即(并行)处理消息?并且在新消息传入时立即中止处理旧消息?否,我想在收到邮件后尽快收到订单,一旦收到订单,我就必须处理邮件。因此,首先是消息,然后是订单簿,然后是处理。项目将不断出现并添加到队列中。一旦收到订单簿,我们需要处理队列中已经保存的消息和队列中出现的新消息
while (threadProcessQueueExist)
{
int recordCountNew = concurrentQueue.Count();
if (recordCountNew != 0)
{
if (isOrderBookUpdated)
{
ProcessQueueMessages();
}
}
}