多个线程中的 For 循环

发布于 2024-11-06 00:13:17 字数 254 浏览 0 评论 0 原文

如何在另一个线程中运行每个 for 循环调用,但ExternalMethod 的继续应该等待 for 循环中最后一个工作线程的结束(并同步)?

ExternalMethod()
{
    //some calculations
    for (int i = 0; i < 10; i++)
    {
        SomeMethod(i);
    }
    //continuation ExternalMethod
}

How can I run each call for loop in another thread, but continuation of ExternalMethod should wait to ending of last working thread from for loop (and synchronize) ?

ExternalMethod()
{
    //some calculations
    for (int i = 0; i < 10; i++)
    {
        SomeMethod(i);
    }
    //continuation ExternalMethod
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鞋纸虽美,但不合脚ㄋ〞 2024-11-13 00:13:17

一种方法是使用 ManualResetEvent

考虑以下代码(请注意,这不应该被视为一个工作示例,因为它停留在 OSX 上,所以没有 VS 或 C# 编译器来手动检查它):

static ManualResetEvent mre = new ManualResetEvent(false);
static int DoneCount = 0;
static int DoneRequired = 9;
void ExternalMethod() {
        mre.Reset();
        for (int i = 0; i < 10; i++) {
                new Thread(new ThreadStart(ThreadVoid)).Start();
        }
        mre.WaitOne();
}

void ThreadVoid() {
        Interlocked.Increment(ref DoneCount);   

        if (DoneCount == DoneRequired) {
                mre.Set();
        }
}

重要 - 这可能不是这不是最好的方法,只是使用 ManualResetEvent 的示例,它将完全满足您的需求。

如果您使用的是 .NET 4.0,则可以使用 Parallel.For 循环 - 在此解释

One approach would be to use a ManualResetEvent.

Consider the following code (note that this should not be taken as a working example, stuck on OSX so don't have VS nor a C# compiler to hand to check this over):

static ManualResetEvent mre = new ManualResetEvent(false);
static int DoneCount = 0;
static int DoneRequired = 9;
void ExternalMethod() {
        mre.Reset();
        for (int i = 0; i < 10; i++) {
                new Thread(new ThreadStart(ThreadVoid)).Start();
        }
        mre.WaitOne();
}

void ThreadVoid() {
        Interlocked.Increment(ref DoneCount);   

        if (DoneCount == DoneRequired) {
                mre.Set();
        }
}

IMPORTANT - This possibly isn't the best way to do it, just an example of using ManualResetEvent, and it will suit your needs perfectly fine.

If you're on .NET 4.0 you can use a Parallel.For loop - explained here.

孤檠 2024-11-13 00:13:17
System.Threading.Tasks.Parallel.For(0, 10, (i) => SomeMethod(i));
System.Threading.Tasks.Parallel.For(0, 10, (i) => SomeMethod(i));
燃情 2024-11-13 00:13:17

一种方法是使用 CountdownEvent

ExternalMethod()
{
    //some calculations
    var finished = new CountdownEvent(1);
    for (int i = 0; i < 10; i++)
    {
        int capture = i; // This is needed to capture the loop variable correctly.
        finished.AddCount();
        ThreadPool.QueueUserWorkItem(
          (state) =>
          {
            try
            {
              SomeMethod(capture);
            }
            finally
            {
              finished.Signal();
            }
          }, null);
    }
    finished.Signal();
    finished.Wait();
    //continuation ExternalMethod
}

如果 CountdownEvent 不可用,那么这里有一个替代方法。

ExternalMethod()
{
    //some calculations
    var finished = new ManualResetEvent(false);
    int pending = 1;
    for (int i = 0; i < 10; i++)
    {
        int capture = i; // This is needed to capture the loop variable correctly.
        Interlocked.Increment(ref pending);
        ThreadPool.QueueUserWorkItem(
          (state) =>
          {
            try
            {
              SomeMethod(capture);
            }
            finally
            {
              if (Interlocked.Decrement(ref pending) == 0) finished.Set();
            }
          }, null);
    }
    if (Interlocked.Decrement(ref pending) == 0) finished.Set();
    finished.WaitOne();
    //continuation ExternalMethod
}

请注意,在这两个示例中,for 循环本身都被视为并行工作项(毕竟它位于与其他工作项不同的线程上),以避免第一个工作项可能出现的非常微妙的竞争条件。工作项在下一个工作项排队之前发出该事件信号。

One approach is to use a CountdownEvent.

ExternalMethod()
{
    //some calculations
    var finished = new CountdownEvent(1);
    for (int i = 0; i < 10; i++)
    {
        int capture = i; // This is needed to capture the loop variable correctly.
        finished.AddCount();
        ThreadPool.QueueUserWorkItem(
          (state) =>
          {
            try
            {
              SomeMethod(capture);
            }
            finally
            {
              finished.Signal();
            }
          }, null);
    }
    finished.Signal();
    finished.Wait();
    //continuation ExternalMethod
}

If CountdownEvent is not available then here is an alternate approach.

ExternalMethod()
{
    //some calculations
    var finished = new ManualResetEvent(false);
    int pending = 1;
    for (int i = 0; i < 10; i++)
    {
        int capture = i; // This is needed to capture the loop variable correctly.
        Interlocked.Increment(ref pending);
        ThreadPool.QueueUserWorkItem(
          (state) =>
          {
            try
            {
              SomeMethod(capture);
            }
            finally
            {
              if (Interlocked.Decrement(ref pending) == 0) finished.Set();
            }
          }, null);
    }
    if (Interlocked.Decrement(ref pending) == 0) finished.Set();
    finished.WaitOne();
    //continuation ExternalMethod
}

Note that in both examples the for loop itself is treating as a parallel work item (it is on a separate thread from the other work items afterall) to avoid a really subtle race condition that might occur if the first work item signals the event before the next work item is queued.

赴月观长安 2024-11-13 00:13:17

对于 .NET 3.5,可能是这样的:

Thread[] threads = new Thread[10];

for (int x = 0; x < 10; x++)
{
    threads[x] = new Thread(new ParameterizedThreadStart(ThreadFun));
    threads[x].Start(x);
}

foreach (Thread thread in threads) thread.Join();

使用 Join() 方法可能看起来违反直觉,但由于您实际上正在执行 WaitAll 类型模式,因此连接的顺序并不重要被处决。

For .NET 3.5, maybe something like this:

Thread[] threads = new Thread[10];

for (int x = 0; x < 10; x++)
{
    threads[x] = new Thread(new ParameterizedThreadStart(ThreadFun));
    threads[x].Start(x);
}

foreach (Thread thread in threads) thread.Join();

It may seem counterintuitive to use the Join() method, but since you are effectively doing a WaitAll-type pattern, it doesn't matter what order the joins are executed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文