【问题标题】:How to find out when a specific thread exits (C#)?如何找出特定线程何时退出(C#)?
【发布时间】:2014-12-12 14:06:25
【问题描述】:

我这里有问题。有没有办法以编程方式找出某个线程退出的时刻?我的意思是,即使是 VS 调试器也会在其输出窗口中为您提供该信息。我知道我可以简单地让我的线程引发一个事件,但是当你产生多个线程时这当然会导致问题,所以它们每个都会引发那个事件,除非你使用一些切换变量来确保只有代码中到达该点的第一个线程将引发事件。

这里是在多个线程中执行的方法的开始,这里显示了取消、暂停和退出逻辑。代码的问题点是对事件处理程序(DownloadComplete、DownloadPaused 和 DownloadCanceled)的调用。如您所见,其中一些将仅由到达该点的第一个线程执行一次,然后切换相关的布尔变量,因此其他线程不会再次引发此事件。这里的另一个大问题是线程退出逻辑,当线程找不到要下载的项目并返回并引发下载完成事件时,当然每个线程都会触发该事件。这两种方法都不正确,我目前不知道如何实现我的预期行为。我所需要的只是知道如何找到一种方法来捕捉所有衍生线程中的最后一个结束时的时刻,这样我就可以只引发一次上述所有事件。

请注意,我无法访问 System.Threading.Tasks 命名空间中的类型,因为我的项目针对 .net 2.0。这是我第一次编程比一些类分配更复杂的东西,所以我意识到这段代码很可能很糟糕。

对不起我的英语。

    private void PerformDownload()
    {
        while (true)
        {
            if (askedToCancel)
            {
                lock (lockObj)
                {
                    if (!cancellationPerformed)
                    {
                        cancellationPerformed = true;

                        foreach (DownloadItem di in itemsToProcess)
                            if (di.Status == DownloadItemStatus.Prepared)
                                itemsToProcess.UpdateItemStatus(di.URL, DownloadItemStatus.Canceled);

                        DownloadCanceled();
                    }
                }

                return;
            }

            if (askedToPause)
            {
                lock (lockObj)
                {
                    if (!pausingPerformed)
                    {
                        foreach (DownloadItem di in itemsToProcess)
                            if (di.Status == DownloadItemStatus.Prepared)
                                itemsToProcess.UpdateItemStatus(di.URL, DownloadItemStatus.Paused);

                        DownloadPaused();
                    }
                }

                waitHandle.WaitOne();
            }

            DownloadItem currentItem = null;

            lock (lockObj)
            {
                foreach (DownloadItem di in itemsToProcess)
                    if (di.Status == DownloadItemStatus.Prepared)
                    {
                        currentItem = di;
                        itemsToProcess.UpdateItemStatus(currentItem.URL, DownloadItemStatus.Downloading);
                        break;
                    }
            }

            if (currentItem == null)
            {
                DownloadComplete();
                return;
            }

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    您可以在计数器上使用Interlocked.Increment()Interlocked.Decrement(),在线程入口点递增,在线程退出时递减。然后,如果计数器不为零,则该线程的至少一个实例正在运行。

    例如:

    private int _threadCounter;
    
    private void ThreadEntryPoint()
    {
        try
        {
            Interlocked.Increment(ref _threadCounter);
            // Do thread stuff here
        }
        finally
        {
            Interlocked.Decrement(ref _threadCounter);
        }
    }
    

    也就是说,恕我直言,不管线程是否正在运行,它可能不是对它重要的最佳设计。也就是说,每当我想到如何使用这些信息时,在我看来,有一种更好的方法来解决这种情况。

    线程的存在是有原因的,而不仅仅是存在。所以你的代码真正应该关心的是这个原因是否已经解决,而不是任何线程是否正在运行。如果没有完整的代码示例,我无法真正评论特定场景。但我怀疑跟踪实际线程存在的用处不大,并且比更面向目标的方法更难维护。

    【讨论】:

    • 嗯,将线程方法的整个代码放在 try-catch 中当然是太多了,但我会尝试按照您建议的方式计算活动线程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多