C# 在按钮单击事件中中止长时间运行的线程

C# 在按钮单击事件中中止长时间运行的线程,c#,wpf,multithreading,C#,Wpf,Multithreading,在我的WPF应用程序中,我有一个长时间运行的进程,它使用BlueBeamQ服务器将文件转换为PDF。当该过程发生时,它不应冻结,因此编写了以下代码来处理该问题: private void btn_convert_Click(object sender, RoutedEventArgs e) { thread = new Thread(new ThreadStart(WorkerMethod)); thread.SetApartmentState(Apartment

在我的WPF应用程序中,我有一个长时间运行的进程,它使用BlueBeamQ服务器将文件转换为PDF。当该过程发生时,它不应冻结,因此编写了以下代码来处理该问题:

private void btn_convert_Click(object sender, RoutedEventArgs e)
{
        thread = new Thread(new ThreadStart(WorkerMethod));
        thread.SetApartmentState(ApartmentState.STA);
        thread.IsBackground = true;
        thread.Name = "PDF";
        thread.Start();
}

WorkerMethod()
{
//code to connect to Q server and conversion goes here
}
现在,当流程开始时,用户将看到一个取消按钮。当用户按cancel时,我想中止已启动的线程。我编写的代码如下:

private void btn_cancel_Click(object sender, RoutedEventArgs e)
    {
        if (thread.Name == "PDF")
            thread.Abort(); 
    }

但是线程不会中止并继续进程。请给我一些有价值的建议。

您可以使用Backgroundworker而不是Thread,如果您的代码包含一个循环,您将能够取消它(您必须在每个循环中测试一个布尔属性)

在你的后台工作代码中:

// in a loop
if (this.backgroundWorker.CancellationPending == false)
{
...
}

您可以使用Backgroundworker而不是Thread,如果您的代码包含一个循环,您将能够取消它(您必须在每个循环中测试一个布尔属性)

在你的后台工作代码中:

// in a loop
if (this.backgroundWorker.CancellationPending == false)
{
...
}

只要有可能,您应该避免中止。搜索如何优雅地取消线程-当线程代码调用其他您无法影响的代码时,如第三方库方法或类似的方法,这是无法完成的

例如,如果线程方法执行以下操作:

WorkerMethod()
{
    CallFunctionInExternalDLL();
}
WorkerMethod()
{
    CallFunctionInExternalDLL();
    if (m_threadAborted)
        RollBackWhatFunctionDid();
}
WorkerMethod()
{
    while (true)
    {
        CallFunctionInExternalDLL();
    }
}
private volatile bool m_threadAborted = false;
它不能正常中止

要“取消”这样一个线程,最好向该线程指示它应该取消(例如,使用
bool
标志),并让该线程回滚其结果(例如,删除创建的PDF或类似内容)。然后,应用程序可以继续运行,就像线程从未启动一样

例如,您的代码可能如下所示:

WorkerMethod()
{
    CallFunctionInExternalDLL();
}
WorkerMethod()
{
    CallFunctionInExternalDLL();
    if (m_threadAborted)
        RollBackWhatFunctionDid();
}
WorkerMethod()
{
    while (true)
    {
        CallFunctionInExternalDLL();
    }
}
private volatile bool m_threadAborted = false;
如果您的线程如下所示:

WorkerMethod()
{
    CallFunctionInExternalDLL();
}
WorkerMethod()
{
    CallFunctionInExternalDLL();
    if (m_threadAborted)
        RollBackWhatFunctionDid();
}
WorkerMethod()
{
    while (true)
    {
        CallFunctionInExternalDLL();
    }
}
private volatile bool m_threadAborted = false;
您可以这样做:

WorkerMethod()
{
    while (!m_threadAborted)
    {
        CallFunctionInExternalDLL();
    }

    if (m_threadAborted)
        RollBackStuff();
}
在这些示例中,
m_threadAborted
是一个声明如下的
bool
标志:

WorkerMethod()
{
    CallFunctionInExternalDLL();
}
WorkerMethod()
{
    CallFunctionInExternalDLL();
    if (m_threadAborted)
        RollBackWhatFunctionDid();
}
WorkerMethod()
{
    while (true)
    {
        CallFunctionInExternalDLL();
    }
}
private volatile bool m_threadAborted = false;

只要有可能,您应该避免中止。搜索如何优雅地取消线程-当线程代码调用其他您无法影响的代码时,如第三方库方法或类似的方法,这是无法完成的

例如,如果线程方法执行以下操作:

WorkerMethod()
{
    CallFunctionInExternalDLL();
}
WorkerMethod()
{
    CallFunctionInExternalDLL();
    if (m_threadAborted)
        RollBackWhatFunctionDid();
}
WorkerMethod()
{
    while (true)
    {
        CallFunctionInExternalDLL();
    }
}
private volatile bool m_threadAborted = false;
它不能正常中止

要“取消”这样一个线程,最好向该线程指示它应该取消(例如,使用
bool
标志),并让该线程回滚其结果(例如,删除创建的PDF或类似内容)。然后,应用程序可以继续运行,就像线程从未启动一样

例如,您的代码可能如下所示:

WorkerMethod()
{
    CallFunctionInExternalDLL();
}
WorkerMethod()
{
    CallFunctionInExternalDLL();
    if (m_threadAborted)
        RollBackWhatFunctionDid();
}
WorkerMethod()
{
    while (true)
    {
        CallFunctionInExternalDLL();
    }
}
private volatile bool m_threadAborted = false;
如果您的线程如下所示:

WorkerMethod()
{
    CallFunctionInExternalDLL();
}
WorkerMethod()
{
    CallFunctionInExternalDLL();
    if (m_threadAborted)
        RollBackWhatFunctionDid();
}
WorkerMethod()
{
    while (true)
    {
        CallFunctionInExternalDLL();
    }
}
private volatile bool m_threadAborted = false;
您可以这样做:

WorkerMethod()
{
    while (!m_threadAborted)
    {
        CallFunctionInExternalDLL();
    }

    if (m_threadAborted)
        RollBackStuff();
}
在这些示例中,
m_threadAborted
是一个声明如下的
bool
标志:

WorkerMethod()
{
    CallFunctionInExternalDLL();
}
WorkerMethod()
{
    CallFunctionInExternalDLL();
    if (m_threadAborted)
        RollBackWhatFunctionDid();
}
WorkerMethod()
{
    while (true)
    {
        CallFunctionInExternalDLL();
    }
}
private volatile bool m_threadAborted = false;

您可以使用此处描述的CancellationTokenSource:

static void cancelwiththreadpoolministippet()
{
//线程1:请求者
//创建令牌源。
CancellationTokenSource cts=新的CancellationTokenSource();
//将令牌传递给可取消操作。
ThreadPool.QueueUserWorkItem(新的WaitCallback(DoSomeWork),cts.Token);
//通过在令牌上设置标志请求取消。
cts.Cancel();
}
//线程2:侦听器
静态空隙DoSomeWork(对象obj)
{
CancellationToken=(CancellationToken)obj;
对于(int i=0;i<100000;i++)
{
//模拟工作。
Thread.SpinWait(5000000);
if(令牌.IsCancellationRequested)
{
//如有必要,执行清理。
//... 
//终止操作。
打破
}
}
}
这篇文章介绍了其他可能的方法:

您可以使用此处描述的CancellationTokenSource:

static void cancelwiththreadpoolministippet()
{
//线程1:请求者
//创建令牌源。
CancellationTokenSource cts=新的CancellationTokenSource();
//将令牌传递给可取消操作。
ThreadPool.QueueUserWorkItem(新的WaitCallback(DoSomeWork),cts.Token);
//通过在令牌上设置标志请求取消。
cts.Cancel();
}
//线程2:侦听器
静态空隙DoSomeWork(对象obj)
{
CancellationToken=(CancellationToken)obj;
对于(int i=0;i<100000;i++)
{
//模拟工作。
Thread.SpinWait(5000000);
if(令牌.IsCancellationRequested)
{
//如有必要,执行清理。
//... 
//终止操作。
打破
}
}
}
这篇文章介绍了其他可能的方法:

您能告诉我们您的工作方法代码吗?Thorsten Dittmar所说的是正确的,但根据您连接到“Q服务器”的方式,您可能可以简单地放弃请求。您能告诉我们您的工作方法的代码吗?Thorsten Dittmar所说的是正确的,但根据您连接到“Q服务器”的方式,您可能可以简单地放弃请求。