简体   繁体   English

需要澄清使用任务和线程 C#

[英]Need clarification on using Tasks and Threads C#

I have a program where I have multiple devices plugged in via USB and are connected to my program with HIDSharp.我有一个程序,我通过 USB 插入了多个设备,并使用 HIDSharp 连接到我的程序。 The program I have essentially creates multiple instances of "APData" class and adds the instances to a list to keep track of those APData instances.我的程序基本上创建了多个“APData”class 实例,并将这些实例添加到列表中以跟踪这些 APData 实例。 From there the GUI waits for me to press the start button and when I do the units that are connected and selected for a test will be moved over to a gridview on the GUI and each APData runs in a task to test the device for a certain parameter every 40ms or so.从那里 GUI 等待我按下开始按钮,当我这样做时,连接并选择进行测试的单元将移动到 GUI 上的 gridview 并且每个 APData 在任务中运行以测试设备的某个特定参数每 40ms 左右。 Essentially I have a loop that creates tasks and at the end I use WaitAll to wait for each task to complete.本质上,我有一个创建任务的循环,最后我使用 WaitAll 等待每个任务完成。 The thing is when I only have 2 units the program seems to work perfectly fine.问题是当我只有 2 个单位时,程序似乎运行得很好。 When I move up to 8 the program will begin and appear to work fine but you can clearly see that some of the units begin to slow down or start off very slowly collecting data.当我移动到 8 时,该程序将开始运行并且看起来工作正常,但您可以清楚地看到一些单元开始减慢或开始非常缓慢地收集数据。 This becomes very apparent when after a minute the program and computer begin to slow down and ultimately freeze.当一分钟后程序和计算机开始减速并最终冻结时,这一点变得非常明显。 I even received the blue screen of death which made me really frustrated that I cannot get this completed.我什至收到了蓝屏死机,这让我非常沮丧,因为我无法完成这项工作。

I have tried isolating the GUI to see if that had anything to do with it but that did not appear to be the case.我曾尝试隔离 GUI 以查看是否与它有关,但似乎并非如此。 The class in which the tasks call on is also static and I have made sure that the only data being shared between the tasks is the list that keeps track of the units along with there data that is collected and associated with APData.任务调用的 class 也是 static,我确保任务之间共享的唯一数据是跟踪单元的列表以及收集并与 APData 关联的数据。

At this point I have no idea how I should proceed.在这一点上,我不知道我应该如何进行。 I have tried those two things above, but like I said, the GUI and computer ultimately freeze.我已经尝试了上述两件事,但就像我说的,GUI 和计算机最终会死机。 I suspect that I possibly need to change some parts in the test itself into tasks but that is just a guess.我怀疑我可能需要将测试本身的某些部分更改为任务,但这只是一个猜测。

Here is the code that I call which creates a task inside a foreach loop and runs a test on each device.这是我调用的代码,它在 foreach 循环中创建一个任务并在每个设备上运行一个测试。

foreach (APData ap in lst)
{
    bool inputmode = ConnectionManager.StartAutomaticSampling(ap);
    var t1 = new Task(() =>
    {
        while (ConnectionManager.ComparedTime < 1)
        {
            ConnectionManager.BeginNoiseTest(ap,APNG_Application.Program.unit, inputmode);
            date = DateTime.Now; // Update time.
            ConnectionManager.ComparedTime = DateTime.Compare(date, endTime);
        }

        ap.DoneBeingTested = true;
        ConnectionManager.NoiseTestEnded(ap, APNG_Application.Program.unit);
        CalculateSNR(APNG_Application.Program.unit, ap);
        saveFile(APNG_Application.Program.unit, ap);
    });

    t1.Start();
}
Task.WaitAll(Task.Delay(timeLimit));

Running this piece of code ConnectionManager.BeginNoiseTest(ap,APNG_Application.Program.unit, inputmode);运行这段代码ConnectionManager.BeginNoiseTest(ap,APNG_Application.Program.unit, inputmode); begins the test for each APData inside the foreach loop and is the main culprit for freezing the program and computer.在 foreach 循环中开始对每个 APData 进行测试,是冻结程序和计算机的罪魁祸首。

Is my understanding of Tasks wrong?我对任务的理解是错误的吗? I thought creating multiple tasks can make things run a little fast and asynchronous as well?我认为创建多个任务也可以使事情运行得更快和异步? Should I be using threads maybe?我应该使用线程吗? Is my CPU usage being consumed by just assigning 8 tasks?仅分配 8 个任务是否会消耗我的 CPU 使用率?

If there is any piece of code you wish to see just comment and I will be sure to reply with it!如果您希望看到任何代码,请发表评论,我一定会回复!

Your issue is that you are beginning a bunch of asynchronous calls in a loop, but only ending one of them.您的问题是您正在循环中开始一堆异步调用,但只结束其中一个。

Your ConnectionManager.BeginNoiseTest is using the old Begin End pattern of tasks.您的ConnectionManager.BeginNoiseTest正在使用旧的Begin End任务模式。 Whereas you are using the newer Task pattern.而您正在使用更新的Task模式。 It appears that this ConnectionManager class is your own, if so it shouldn't be difficult to convert it.看来这个ConnectionManager class 是你自己的,如果是这样,转换它应该不难。

You are also capturing a date variable, whereas it seems it should be unique to each task.您还捕获了一个date变量,而它似乎对每个任务都应该是唯一的。

Furthermore, Task.WaitAll(Task.Delay(timeLimit));此外, Task.WaitAll(Task.Delay(timeLimit)); is not looking at the tasks you created, it's only waiting for the delay.不是在看你创建的任务,它只是在等待延迟。

var list = new List<Task>();
foreach (APData ap in lst)
{
    bool inputmode = ConnectionManager.StartAutomaticSampling(ap);
    var t1 = Task.Run(async () =>
    {
        while (ConnectionManager.ComparedTime < 1)
        {
            await ConnectionManager.NoiseTestAsync(ap, APNG_Application.Program.unit, inputmode);
            var date = DateTime.Now; // Update time.
            ConnectionManager.ComparedTime = DateTime.Compare(date, endTime);
        }

        ap.DoneBeingTested = true;
        CalculateSNR(APNG_Application.Program.unit, ap);
        await saveFileAsync(APNG_Application.Program.unit, ap);  // file IO should be async also
    });

    list.Add(t1);
}

Task.WaitAll(tasks.ToArray(), timeLimit);

Ideally you should also not use Task.WaitAll , as that can cause a deadlock.理想情况下,您也不应该使用Task.WaitAll ,因为这会导致死锁。 Instead you should do await Task.WhenAll(tasks.ToArray(), timeLimit);相反,您应该await Task.WhenAll(tasks.ToArray(), timeLimit);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM