gpt4 book ai didi

c# - 我如何让我的方法等待所有线程完成?

转载 作者:行者123 更新时间:2023-11-30 13:24:02 24 4
gpt4 key购买 nike

我有一个方法可以触发线程来完成一些工作。将有 2 个线程异步运行一段时间,当调用它们的回调方法时,回调会触发另一个线程,直到所有工作完成。如何让我的方法等待所有这些线程完成并被解雇?

最佳答案

如果这是 .Net 4.0,您可以使用 CountdownEvent

const int threads = 10;
using( CountdownEvent evt = new CountdownEvent(threads) )
{
for( int x = 0; x < threads; ++x )
{
ThreadPool.QueueUserWorkItem((state) =>
{
// Do work here
((CountdownEvent)state).Signal();
}, evt);
}

evt.Wait();
}
Console.WriteLine("Everyone finished!");

Thread.Join 不是一个选项时(例如,如果您正在使用线程池),这具有工作的优势,并且比使用等待句柄更好地缩放(因为 WaitHandle .WaitAll 最多有 64 个句柄,您也不需要分配那么多对象。

请注意,如果您使用的是 .Net 4,您还可以使用任务并行库,它使此类事情变得更容易。

更新:

既然你说这不是 .Net 4.0,这里有一个可以在 .Net 3.5 中使用的 CountdownEvent 的简单版本。我最初写它是因为我需要一个可以在 Mono 中使用的 CountdownEvent,当时 Mono 还不支持 .Net 4。它不像真正的那样灵活,但它可以满足您的需要:

/// <summary>
/// Represents a synchronization primitive that is signaled when its count reaches zero.
/// </summary>
/// <remarks>
/// <para>
/// This class is similar to but less versatile than .Net 4's built-in CountdownEvent.
/// </para>
/// </remarks>
public sealed class CountdownEvent : IDisposable
{
private readonly ManualResetEvent _reachedZeroEvent = new ManualResetEvent(false);
private volatile int _count;
private volatile bool _disposed;

/// <summary>
/// Initializes a new instance of the <see cref="CountdownEvent"/> class.
/// </summary>
/// <param name="initialCount">The initial count.</param>
public CountdownEvent(int initialCount)
{
_count = initialCount;
}

// Disable volatile not treated as volatile warning.
#pragma warning disable 420

/// <summary>
/// Signals the event by decrementing the count by one.
/// </summary>
/// <returns><see langword="true" /> if the count reached zero and the event was signalled; otherwise, <see langword="false"/>.</returns>
public bool Signal()
{
CheckDisposed();

// This is not meant to prevent _count from dropping below zero (that can still happen due to race conditions),
// it's just a simple way to prevent the function from doing unnecessary work if the count has already reached zero.
if( _count <= 0 )
return true;

if( Interlocked.Decrement(ref _count) <= 0 )
{
_reachedZeroEvent.Set();
return true;
}
return false;
}

#pragma warning restore 420

/// <summary>
/// Blocks the calling thread until the <see cref="CountdownEvent"/> is set.
/// </summary>
public void Wait()
{
CheckDisposed();
_reachedZeroEvent.WaitOne();
}

/// <summary>
/// Blocks the calling thread until the <see cref="CountdownEvent"/> is set, using a <see cref="TimeSpan"/> to measure the timeout.
/// </summary>
/// <param name="timeout">The timeout to wait, or a <see cref="TimeSpan"/> representing -1 milliseconds to wait indefinitely.</param>
/// <returns><see langword="true"/> if the <see cref="CountdownEvent"/> was set; otherwise, <see langword="false"/>.</returns>
public bool Wait(TimeSpan timeout)
{
CheckDisposed();
return _reachedZeroEvent.WaitOne(timeout, false);
}

/// <summary>
/// Blocks the calling thread until the <see cref="CountdownEvent"/> is set, using a 32-bit signed integer to measure the timeout.
/// </summary>
/// <param name="millisecondsTimeout">The timeout to wait, or <see cref="Timeout.Infinite"/> (-1) to wait indefinitely.</param>
/// <returns><see langword="true"/> if the <see cref="CountdownEvent"/> was set; otherwise, <see langword="false"/>.</returns>
public bool Wait(int millisecondsTimeout)
{
CheckDisposed();
return _reachedZeroEvent.WaitOne(millisecondsTimeout, false);
}

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
if( !_disposed )
{
if( disposing )
((IDisposable)_reachedZeroEvent).Dispose();
_disposed = true;
}
}

private void CheckDisposed()
{
if( _disposed )
throw new ObjectDisposedException(typeof(CountdownEvent).FullName);
}
}

关于c# - 我如何让我的方法等待所有线程完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6790499/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com