Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF从主线程停止后台工作_C#_Wpf_Multithreading - Fatal编程技术网

C# WPF从主线程停止后台工作

C# WPF从主线程停止后台工作,c#,wpf,multithreading,C#,Wpf,Multithreading,我有一个后台工作人员,在后台执行工作。该工作在命令提示符下运行某个.exe应用程序,并等待显示输出。有时.exe应用程序是堆栈式的,或者需要花费很多时间。我想在一分钟后让工人停下来,以防它仍在运行。 问题是我有一个进度条,在主线程中运行1分钟。我想在主线程(UI)的进度条已满(1分钟后)时停止工作进程。这是我的密码: private void btnTest_Click(object sender, RoutedEventArgs e) { wTest = ne

我有一个后台工作人员,在后台执行工作。该工作在命令提示符下运行某个.exe应用程序,并等待显示输出。有时.exe应用程序是堆栈式的,或者需要花费很多时间。我想在一分钟后让工人停下来,以防它仍在运行。 问题是我有一个进度条,在主线程中运行1分钟。我想在主线程(UI)的进度条已满(1分钟后)时停止工作进程。这是我的密码:

    private void btnTest_Click(object sender, RoutedEventArgs e)
    {

        wTest = new BackgroundWorker();
        wTest .DoWork += new DoWorkEventHandler(wTest _DoWork);
        wTest .RunWorkerCompleted += wTest _RunWorkerCompleted;
        wTest .WorkerReportsProgress = true;
        wTest .WorkerSupportsCancellation = true;
        wTest .RunWorkerAsync();

        while (pbTest.Value < 91)
        {               
            if (!wTest.CancellationPending)
            {
                pbTest.Value = (pbTest.Value + 100/60);
                Thread.Sleep(1000);
            }
            Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background,
                                       new ThreadStart(delegate { }));
        }
    }

    void wTest_DoWork(object sender, DoWorkEventArgs e)
    {
        //call .exe application and wait for output
    }
private void btnTest\u单击(对象发送方,路由目标)
{
wTest=新的BackgroundWorker();
wTest.DoWork+=新的DoWorkEventHandler(wTest\U DoWork);
wTest.RunWorkerCompleted+=wTest\u RunWorkerCompleted;
wTest.WorkerReportsProgress=true;
wTest.workersupport扫描单元=真;
wTest.RunWorkerAsync();
而(pbTest.Value<91)
{               
如果(!wTest.CancellationPending)
{
pbTest.Value=(pbTest.Value+100/60);
睡眠(1000);
}
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background,
新线程开始(委托{});
}
}
void wTest_DoWork(对象发送方,DoWorkEventArgs e)
{
//调用.exe应用程序并等待输出
}

我该怎么做?

您需要做的是让您的
DoWork
代表检查
e.Cancel
(在
DoWorkEventArgs
中)属性设置为
true
。如果
DoWork
被阻塞,比如等待
StandardOutput
,那么这根本不可能

另一种方法是传递
进程。WaitForExit
一个
int
说明它应该等待输出多长时间:

process.WaitForExit(60000);

如果您使用的是.net 4.5,则可以使用
任务
类和关联的
取消toksource
取消令牌
类。请注意,任务支持通过
IProgress
界面报告进度。斯蒂芬·克利里对此很在行

如果您正在执行的工作没有提供异步接口,您可以使用
任务。运行
执行它,并传递
取消令牌
以监视取消。在您执行工作时,您需要监视令牌的取消。一种方法是调用,如果在
CancellationTokenSource
上调用了
Cancel
,则调用将抛出
operationcanceledexception
CancellationTokenSource
还支持在特定时间后取消,这对于您的场景来说非常方便

private CancellationTokenSource cts;

private void btnTest_Click(object sender, RoutedEventArgs e)
{
    if(cts == null)
    {
        cts = new CancellationTokenSource(new TimeSpan(0, 0, 60)); // cancel after 60 seconds
    }

    await Task.Run( () => Work(), cts.Token);

    cts = null;
}

void Work(CancellationToken token)
{
   // do work
  token.ThrowIfCancellationRequested();
  // do work
}

您需要做两件事才能取消您的
后台工作人员的工作。首先,您需要检查
DoWork
处理程序方法中的:

private void wTest_DoWork(object sender, DoWorkEventArgs e)
{
    //call .exe application and wait for output
    if (worker.CancellationPending)
    {   
        e.Cancel = true;
    }
}
然后,当您想要取消工作时,您应该在您的
后台工作人员中调用此选项:

backgroundWorker.CancelAsync();
但是,由于您没有按预期使用
BackgroundWorker
,因此我认为这对您不起作用。如果您正在等待第三方应用程序启动,则无法将
e.Cancel
属性设置为
true


老实说,我不太明白你为什么要用一个
后台工作人员来启动一个流程。
Process.Start
方法不需要花费时间来完成,因为它不等待任何响应。在我看来,您最好监视并调用。

停止后台工作程序或停止它启动的进程?我想停止工作程序。我可以估计它也会停止进程吗?我正在使用.NET3.5。这个类包含在.NET 4Ok中,我要说的是,我的答案是针对.NET 4.5的。有什么方法可以为.NET 3.5实现它吗?不是使用
async
wait
,但是如果您想使用任务并行库,您可以为.NET 3.5尝试这个端口。但如果可以,最好升级到.NET4.0或4.5。这给了你更多的选择