多线程时出现意外结果 [英] Unexpected results when multi threading

查看:94
本文介绍了多线程时出现意外结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,该函数将由以start和end参数启动的线程调用.在单主线程上运行时,该函数运行良好.但是,当我尝试对其进行多线程处理时,代码会中断.

I have a function that is to be called by a thread initiated with a start and end parameter. The function works fine when run on single, main thread. However, when I try multi threading on it, the code breaks.

功能如下:

static void processThread(long startLimit, long endLimit)
    {
        long rangeLimit = startLimit;
        while (startLimit < endLimit) {
            rangeLimit = rangeLimit + 100;
            startLimit++;
            Console.WriteLine("Processed for " + startLimit + ", " + rangeLimit); 
            startLimit = rangeLimit;
        }
    }

我从main称呼它为:

I am calling it from main as::

int threadCount = 4;
long[] startPoints = new long[threadCount];
long[] endPoints = new long[threadCount];
if ((endLimit / 100) % threadCount == 0)
{
    for (int i = 0; i < threadCount; i++)
    {
        endPoints[i] = endLimit * (i + 1) / threadCount;
    }
    startPoints[0] = 0;
    for (int i = 1; i < threadCount; i++)
    {
        startPoints[i] = endPoints[i - 1];
    }
}
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++)
{
    threads[i] = new Thread(() => processThread(startPoints[i], endPoints[i]));
    threads[i].Start();
    Console.WriteLine("Started for " + startPoints[i] + ", " + endPoints[i]); 
}

预期结果类似于

Processed for 1, 100
Processed for 101, 200
Processed for 201, 300
Processed for 301, 400
Processed for 401, 500
Processed for 501, 600
Processed for 601, 700
Processed for 701, 800
.....

以此类推...但是我得到的是:

And so on... But what I am getting is:

Started for 0, 2500
Started for 2500, 5000
Processed for 5001, 5100
Processed for 5101, 5200
Processed for 5201, 5300
Processed for 5301, 5400
Processed for 5401, 5500
Processed for 5501, 5600
Processed for 5601, 5700
Processed for 5001, 5100
Started for 5000, 7500
Processed for 5001, 5100
Processed for 5101, 5200
Processed for 5201, 5300
Processed for 5301, 5400
Processed for 5401, 5500
Processed for 5501, 5600
Processed for 5601, 5700
Processed for 5701, 5800
Processed for 5801, 5900
Processed for 5901, 6000
Processed for 6001, 6100
Processed for 6101, 6200
Started for 7500, 10000
Processed for 6201, 6300
Processed for 6301, 6400
Processed for 6401, 6500
Processed for 6501, 6600
Processed for 5701, 5800

具有多个重复值,并且没有0-2500范围内的值.我也尝试了Task.Factory,并得到了相同的结果.

Which has many repeated values and has none from the range 0-2500. I also tried with Task.Factory, and got the same result.

在此方面的任何帮助将不胜感激.

Any help on this would be greatly appreciated.

推荐答案

我不会为您的问题提供正确的解决方案,只是为了解决您的输出问题,为了阻止主线程,您最终错过了此解决方案孩子们完成了:

I would not comment on the correct solution for your problem, just to fix your output, you are missing this at the end in order to block main thread before all child ones are finished:

                Console.WriteLine("Started for " + startPoints[i] + ", " + endPoints[i]);
        }
        foreach (var thread in threads)
        {
            thread.Join();
        }

        Console.ReadKey();
    }

我在代码中修复了另一件事:

One more thing I have fixed in the code:

            int count = i;
            threads[i] = new Thread(() =>
            {
                processThread(startPoints[count], endPoints[count]);
            });

为了防止在从子线程进行评估时我无效的潜在问题.

To prevent potential problems where i is invalid when evaluated from child threads.

我还要说,除非您真的需要使用旧的" .net线程,否则应使用其他评论者的建议使用并行库或Tasks.

I would also say that unless you really need to use "old" .net Threads, Parallel library or Tasks should be used for this as suggested by other commenters.

使用Task方法重写了同样的内容(为了更好地说明,我将其保留为将Task替换为Thread).

The same just rewritten with Task approach (I have kept it as is just replaced the Thread with Task for better illustration).

var factory = new TaskFactory();
        var tasks = new List<Task>();
        for (int i = 0; i < threadCount; i++)
        {
            int count = i;
            Task task = factory.StartNew(() =>
            {
                processThread(startPoints[count], endPoints[count]);
            });
            tasks.Add(task);
            Console.WriteLine("Started for " + startPoints[i] + ", " + endPoints[i]);
        }

        Task.WaitAll(tasks.ToArray());

这篇关于多线程时出现意外结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆