C# 窗口关闭时线程不终止

C# 窗口关闭时线程不终止,c#,wpf,reflection,C#,Wpf,Reflection,我有一个名为Manager的类,它有一个线程。当应用程序关闭时,我希望找到Manager的所有实例以中止其线程。我该怎么做 我已经在它的UserControl中尝试了unload事件,但它只在UserControl关闭时起作用,而不是整个应用程序 现在我想使用其窗口的Closed事件,但我不想在那里有管理器引用。有什么想法吗?如果您将threads IsBackground属性设置为true,它将不会阻止在退出时终止的应用程序如果您将threads IsBackground属性设置为true,它

我有一个名为
Manager
的类,它有一个线程。当应用程序关闭时,我希望找到
Manager
的所有实例以中止其线程。我该怎么做

我已经在它的
UserControl
中尝试了
unload
事件,但它只在
UserControl
关闭时起作用,而不是整个应用程序


现在我想使用其
窗口的
Closed
事件
,但我不想在那里有
管理器
引用。有什么想法吗?

如果您将threads IsBackground属性设置为true,它将不会阻止在退出时终止的应用程序

如果您将threads IsBackground属性设置为true,它将不会阻止在退出时终止的应用程序

将线程设置为后台线程,并在程序结束时自动终止。您可以通过属性设置线程的类型


但是,我不认为这是一个干净的解决方案。使用
while(!terminate){…}
循环更简洁,这样单个线程就可以完成任务,例如写入文件。如果只是终止写入文件的线程,则可能最终导致文件损坏。这不仅适用于文件,也适用于其他项目。

将线程设置为后台线程,并在程序结束时自动终止。您可以通过属性设置线程的类型


但是,我不认为这是一个干净的解决方案。使用
while(!terminate){…}
循环更简洁,这样单个线程就可以完成任务,例如写入文件。如果只是终止写入文件的线程,则可能最终导致文件损坏。这不仅适用于文件,也适用于其他项。

在Manager类中实现
IDisposable
,并确保在
Dispose
方法中关闭并取消分配任何资源,例如
线程
。当垃圾收集器在应用程序关闭后开始清理时,将调用此函数,前提是您遵循了正常的IDisposable模式,如下所示:

public class ComplexResourceHolder : IDisposable {

    private IntPtr buffer; // unmanaged memory buffer
    private SafeHandle resource; // disposable handle to a resource

    public ComplexResourceHolder(){
        this.buffer = ... // allocates memory
        this.resource = ... // allocates the resource
    }

    protected virtual void Dispose(bool disposing){
            ReleaseBuffer(buffer); // release unmanaged memory
        if (disposing){ // release other disposable objects
            if (resource!= null) resource.Dispose();
        }
    }

    ~ ComplexResourceHolder(){
        Dispose(false);
    }

    public void Dispose(){
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

在Manager类中实现
IDisposable
,并确保在
Dispose
方法中关闭并取消分配任何资源,例如
Threads
。当垃圾收集器在应用程序关闭后开始清理时,将调用此函数,前提是您遵循了正常的IDisposable模式,如下所示:

public class ComplexResourceHolder : IDisposable {

    private IntPtr buffer; // unmanaged memory buffer
    private SafeHandle resource; // disposable handle to a resource

    public ComplexResourceHolder(){
        this.buffer = ... // allocates memory
        this.resource = ... // allocates the resource
    }

    protected virtual void Dispose(bool disposing){
            ReleaseBuffer(buffer); // release unmanaged memory
        if (disposing){ // release other disposable objects
            if (resource!= null) resource.Dispose();
        }
    }

    ~ ComplexResourceHolder(){
        Dispose(false);
    }

    public void Dispose(){
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

尽管使用IsBackground属性可以工作,但要执行额外的清理,您可以使用Manager类上的一些静态成员跟踪正在运行的线程,并在应用程序退出时循环该集合。

尽管使用IsBackground属性可以工作,但要执行额外的清理,您可以使用Manager类上的一些静态成员来跟踪正在运行的线程,并在应用程序退出时循环该集合。

请将其他答案和注释作为重构代码和创建其他解决方案的理由。但是,如果您有某些原因要提交,可以创建一个静态列表,其中包含每个管理器的实例,这些实例可以在退出时中止:

class Manager
{
    //A WeakReference prevents memory leaks when you dispose of managers in another place
    private static readonly List<WeakReference<Manager>> Instances 
             = new List<WeakReference<Manager>>();

    public static void AbortAll()
    {
        foreach (var weakReference in Instances)
        {
            Manager current;
            if (weakReference.TryGetTarget(out current))
                current.Abort();
        }
        Instances.Clear();
    }

    private void Abort()
    {
        //...
    }

    public Manager()
    {
        //...
        Instances.Add(new WeakReference<Manager>(this));
    }
}

请将其他答案和注释作为重构代码并创建另一个解决方案的理由。但是,如果您有某些原因要提交,可以创建一个静态列表,其中包含每个管理器的实例,这些实例可以在退出时中止:

class Manager
{
    //A WeakReference prevents memory leaks when you dispose of managers in another place
    private static readonly List<WeakReference<Manager>> Instances 
             = new List<WeakReference<Manager>>();

    public static void AbortAll()
    {
        foreach (var weakReference in Instances)
        {
            Manager current;
            if (weakReference.TryGetTarget(out current))
                current.Abort();
        }
        Instances.Clear();
    }

    private void Abort()
    {
        //...
    }

    public Manager()
    {
        //...
        Instances.Add(new WeakReference<Manager>(this));
    }
}

manager类是否有对其运行的线程的引用?如果没有,您将如何找到属于管理器的线程?你使用线程池吗?如果是这样,那么管理器可能比线程多。通常:对象在内存中,代码在线程中。他们不需要有任何共同点。
有什么想法吗?
-是的。立即删除所有代码,重新开始,确保遵守关注点分离原则。UI不是“启动线程”的正确位置,
UserControl
没有“线程”(不管这意味着什么)。创建适当的ViewModel并管理ViewModel级别所需的任何线程。是的,它有一个参考。我没有使用线程池,因为我的任务需要优先级。@HighCore。我的userControl不知道线程。uc中的某些VM有一个具有线程的管理器。@Bizz在这种情况下,您还应该在ViewModel级别管理这些线程的(优雅)终止,而UI与此无关。请编辑您的问题并添加相关代码,并删除关于
UserControl
的部分,如果您处理的是ViewModel,则该部分与问题无关。manager类是否有对其运行线程的引用?如果没有,您将如何找到属于管理器的线程?你使用线程池吗?如果是这样,那么管理器可能比线程多。通常:对象在内存中,代码在线程中。他们不需要有任何共同点。
有什么想法吗?
-是的。立即删除所有代码,重新开始,确保遵守关注点分离原则。UI不是“启动线程”的正确位置,
UserControl
没有“线程”(不管这意味着什么)。创建适当的ViewModel并管理ViewModel级别所需的任何线程。是的,它有一个参考。我没有使用线程池,因为我的任务需要优先级。@HighCore。我的userControl不知道线程。uc中的某些VM有一个具有线程的管理器。@Bizz在这种情况下,您还应该在ViewModel级别管理这些线程的(优雅)终止,而UI与此无关。请编辑您的问题并添加相关代码,删除关于
UserControl
的部分,如果您处理的是ViewModel,则该部分与问题无关。我认为终止此线程不会损坏任何内容。但我记住了这一点。谢谢你提供的信息,我想