Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.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# 如何中止/取消第三方物流任务?_C#_.net_Multithreading_Task_Abort - Fatal编程技术网

C# 如何中止/取消第三方物流任务?

C# 如何中止/取消第三方物流任务?,c#,.net,multithreading,task,abort,C#,.net,Multithreading,Task,Abort,在线程中,我创建了一些System.Threading.Task,并启动每个任务 当我执行.Abort()终止线程时,任务不会中止 如何将.Abort()传输到我的任务?任务正在线程池上执行(至少,如果使用默认工厂),因此中止线程不会影响任务。有关中止任务的信息,请参阅msdn上的。您不能。任务使用线程池中的后台线程。另外,不建议使用Abort方法取消线程。您可以查看,它解释了使用取消令牌取消任务的正确方法。下面是一个例子: class Program { static void Mai

在线程中,我创建了一些
System.Threading.Task
,并启动每个任务

当我执行
.Abort()
终止线程时,任务不会中止


如何将
.Abort()
传输到我的任务?

任务正在线程池上执行(至少,如果使用默认工厂),因此中止线程不会影响任务。有关中止任务的信息,请参阅msdn上的。

您不能。任务使用线程池中的后台线程。另外,不建议使用Abort方法取消线程。您可以查看,它解释了使用取消令牌取消任务的正确方法。下面是一个例子:

class Program
{
    static void Main()
    {
        var ts = new CancellationTokenSource();
        CancellationToken ct = ts.Token;
        Task.Factory.StartNew(() =>
        {
            while (true)
            {
                // do some heavy work here
                Thread.Sleep(100);
                if (ct.IsCancellationRequested)
                {
                    // another thread decided to cancel
                    Console.WriteLine("task canceled");
                    break;
                }
            }
        }, ct);

        // Simulate waiting 3s for the task to complete
        Thread.Sleep(3000);

        // Can't wait anymore => cancel this task 
        ts.Cancel();
        Console.ReadLine();
    }
}

任务具有通过取消的一流支持。使用取消令牌创建任务,并通过这些令牌明确取消任务。

您可以使用
取消令牌来控制任务是否被取消。你是说在它开始之前就中止它(“别担心,我已经做过了”),还是实际上在中途中断了它?如果是前者,则
CancellationToken
可能会有所帮助;如果是后者,您可能需要实现自己的“纾困”机制,并在任务执行的适当时刻检查是否应该快速失败(您仍然可以使用CancellationToken来帮助您,但它需要更多的手动操作)

MSDN有一篇关于取消任务的文章:

您不应该直接尝试这样做。将任务设计为使用,然后以这种方式取消它们

此外,我还建议您将主线程更改为通过CancellationToken运行。调用
Thread.Abort()
是一个坏主意-它会导致各种难以诊断的问题。相反,该线程可以使用与您的任务相同的
CancellationTokenSource
来触发取消所有任务和主线程


这将导致一种更简单、更安全的设计。

这类事情是
中止
被弃用的逻辑原因之一。首先也是最重要的一点,如果可能的话,不要使用
Thread.Abort()
来取消或停止线程。
Abort()
只能用于强制杀死没有响应更和平的请求的线程,以便及时停止


也就是说,您需要提供一个共享取消指示器,其中一个线程设置并等待,而另一个线程定期检查并正常退出。NET 4包含一个专门为此目的而设计的结构。

如果捕获运行任务的线程,则可以很容易地中止任务。下面是一个示例代码来演示这一点:

void Main()
{
    Thread thread = null;

    Task t = Task.Run(() => 
    {
        //Capture the thread
        thread = Thread.CurrentThread;

        //Simulate work (usually from 3rd party code)
        Thread.Sleep(1000);

        //If you comment out thread.Abort(), then this will be displayed
        Console.WriteLine("Task finished!");
    });

    //This is needed in the example to avoid thread being still NULL
    Thread.Sleep(10);

    //Cancel the task by aborting the thread
    thread.Abort();
}
我使用Task.Run()来展示这方面最常见的用例-使用旧单线程代码的任务的舒适性,它不使用CancellationTokenSource类来确定是否应该取消它。

类似于建议,这可以通过以下方式完成:

int Foo(CancellationToken token)
{
    Thread t = Thread.CurrentThread;
    using (token.Register(t.Abort))
    {
        // compute-bound work here
    }
}

虽然它可以工作,但不建议使用这种方法。如果您可以控制任务中执行的代码,那么最好正确处理取消操作。

我使用混合方法来取消任务

  • 首先,我试着礼貌地取消它,使用
  • 如果它仍然在运行(例如,由于开发人员的错误),那么就用一种老派的方法来破坏它的行为并杀死它
签出以下示例:

private CancellationTokenSource taskToken;
private AutoResetEvent awaitReplyOnRequestEvent = new AutoResetEvent(false);

void Main()
{
    // Start a task which is doing nothing but sleeps 1s
    LaunchTaskAsync();
    Thread.Sleep(100);
    // Stop the task
    StopTask();
}

/// <summary>
///     Launch task in a new thread
/// </summary>
void LaunchTaskAsync()
{
    taskToken = new CancellationTokenSource();
    Task.Factory.StartNew(() =>
        {
            try
            {   //Capture the thread
                runningTaskThread = Thread.CurrentThread;
                // Run the task
                if (taskToken.IsCancellationRequested || !awaitReplyOnRequestEvent.WaitOne(10000))
                    return;
                Console.WriteLine("Task finished!");
            }
            catch (Exception exc)
            {
                // Handle exception
            }
        }, taskToken.Token);
}

/// <summary>
///     Stop running task
/// </summary>
void StopTask()
{
    // Attempt to cancel the task politely
    if (taskToken != null)
    {
        if (taskToken.IsCancellationRequested)
            return;
        else
            taskToken.Cancel();
    }

    // Notify a waiting thread that an event has occurred
    if (awaitReplyOnRequestEvent != null)
        awaitReplyOnRequestEvent.Set();

    // If 1 sec later the task is still running, kill it cruelly
    if (runningTaskThread != null)
    {
        try
        {
            runningTaskThread.Join(TimeSpan.FromSeconds(1));
        }
        catch (Exception ex)
        {
            runningTaskThread.Abort();
        }
    }
}
private CancellationTokenSource taskToken;
private AutoResetEvent WaitReplyonRequestEvent=新的AutoResetEvent(false);
void Main()
{
//启动一项任务,它什么也不做,只睡1秒钟
LaunchTaskAsync();
睡眠(100);
//停止任务
StopTask();
}
/// 
///在新线程中启动任务
/// 
void LaunchTaskAsync()
{
taskToken=新的CancellationTokenSource();
Task.Factory.StartNew(()=>
{
尝试
{//捕获线程
runningTaskThread=Thread.CurrentThread;
//运行任务
if(taskToken.IsCancellationRequested | |!waitReplyOnRequestEvent.WaitOne(10000))
回来
Console.WriteLine(“任务完成!”);
}
捕获(异常exc)
{
//处理异常
}
},taskToken.Token);
}
/// 
///停止运行任务
/// 
void StopTask()
{
//尝试礼貌地取消任务
if(taskToken!=null)
{
if(taskToken.IsCancellationRequested)
回来
其他的
taskToken.Cancel();
}
//通知正在等待的线程已发生事件
if(waitReplyOnRequestEvent!=null)
waitReplyonRequestEvent.Set();
//如果1秒钟后任务仍在运行,则残酷地杀死它
if(runningTaskThread!=null)
{
尝试
{
runningTaskThread.Join(TimeSpan.FromSeconds(1));
}
捕获(例外情况除外)
{
runningTaskThread.Abort();
}
}
}

要回答Prerak K关于在Task.Factory.StartNew()中不使用匿名方法时如何使用CancellationTokens的问题,请将CancellationToken作为参数传递给以StartNew()开头的方法,如MSDN示例所示

e、 g


我尝试了
CancellationTokenSource
,但我做不到。我用我自己的方式做到了这一点。它是有效的

namespace Blokick.Provider
{
    public class SignalRConnectProvider
    {
        public SignalRConnectProvider()
        {
        }

        public bool IsStopRequested { get; set; } = false; //1-)This is important and default `false`.

        public async Task<string> ConnectTab()
        {
            string messageText = "";
            for (int count = 1; count < 20; count++)
            {
                if (count == 1)
                {
                //Do stuff.
                }

                try
                {
                //Do stuff.
                }
                catch (Exception ex)
                {
                //Do stuff.
                }
                if (IsStopRequested) //3-)This is important. The control of the task stopping request. Must be true and in inside.
                {
                    return messageText = "Task stopped."; //4-) And so return and exit the code and task.
                }
                if (Connected)
                {
                //Do stuff.
                }
                if (count == 19)
                {
                //Do stuff.
                }
            }
            return messageText;
        }
    }
}

如果可以使任务在其自己的线程上创建,并在其
thread
对象上调用
abort
,则可以像线程一样中止任务。默认情况下,任务在线程池线程或调用线程上运行,您通常不希望中止这两个线程

要确保任务获得自己的线程,请创建从
TaskScheduler
派生的自定义计划程序。在您的
QueueTask
实现中,创建一个新的
namespace Blokick.Provider
{
    public class SignalRConnectProvider
    {
        public SignalRConnectProvider()
        {
        }

        public bool IsStopRequested { get; set; } = false; //1-)This is important and default `false`.

        public async Task<string> ConnectTab()
        {
            string messageText = "";
            for (int count = 1; count < 20; count++)
            {
                if (count == 1)
                {
                //Do stuff.
                }

                try
                {
                //Do stuff.
                }
                catch (Exception ex)
                {
                //Do stuff.
                }
                if (IsStopRequested) //3-)This is important. The control of the task stopping request. Must be true and in inside.
                {
                    return messageText = "Task stopped."; //4-) And so return and exit the code and task.
                }
                if (Connected)
                {
                //Do stuff.
                }
                if (count == 19)
                {
                //Do stuff.
                }
            }
            return messageText;
        }
    }
}
namespace Blokick.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MessagePerson : ContentPage
    {
        SignalRConnectProvider signalR = new SignalRConnectProvider();

        public MessagePerson()
        {
            InitializeComponent();

            signalR.IsStopRequested = true; // 2-) And this. Make true if running the task and go inside if statement of the IsStopRequested property.

            if (signalR.ChatHubProxy != null)
            {
                 signalR.Disconnect();
            }

            LoadSignalRMessage();
        }
    }
}