与 new Task(action, token) 结合时,Action 中的参数如何填充
How does the parameter in an Action get filled when combined with new Task(action, token)
简介
首先,我已经阅读了以下文章,但我认为它们没有回答这个问题:
Cancellation token in Task constructor: why?
What is the use of passing CancellationToken to Task Class constructor?
我很清楚token参数的用途。
我的问题
我尝试用内联注释记录代码,让您了解我在哪里遗漏了所有链接。
代码完成了我想要它做的事情:
- 每 2 秒写入一次控制台
- 10 秒后停止
我的问题:"howDoIGetFilled"参数如何获取"token"参数的值。第二个参数用于 Task 实例本身,而不是正在使用的 Action。
如果有任何不清楚的地方,请让我知道你想澄清什么。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TaskDelegatePlayground
{
class Program
{
static void Main(string[] args)
{
var source = new CancellationTokenSource();
var token = source.Token;
Action<object> action = howDoIGetFilled => TestCancellationWithToken((CancellationToken)howDoIGetFilled);
//I understand that this works, as you pass in the token and it gets passed to the "howDoIGetFilled" variable.
//action(token);
//Wrong because it's "hardcoding" the token variable now but I don't understand how the above gets filled in.
//Action<object> action = howDoIGetFilled => TestCancellationWithToken(token);
var task = new Task(action, token);
task.Start();
Thread.Sleep(10000);
//This should cancel the operation
Console.WriteLine("Cancelling");
source.Cancel();
Console.WriteLine("Ended, press any key to close the application.");
Console.ReadKey();
}
public static void TestCancellationWithToken(CancellationToken token)
{
//no intellisense here for token / source
while (true)
{
if (token.IsCancellationRequested)
break;
Console.WriteLine("test");
Thread.Sleep(2000);
}
}
}
}
简答:
当在线程池中调用 Task 时,将执行操作,并且根据它是 Action
还是 Action<T>
,将在有或没有 [=14] 的情况下执行=] 你可以选择传入。
长答案:
正在寻找 Task
的 reference source,这是它被调用的方式:
/// <summary>
/// The actual code which invokes the body of the task. This can be overriden in derived types.
/// </summary>
internal virtual void InnerInvoke()
{
// Invoke the delegate
Contract.Assert(m_action != null, "Null action in InnerInvoke()");
var action = m_action as Action;
if (action != null)
{
action();
return;
}
var actionWithState = m_action as Action<object>;
if (actionWithState != null)
{
actionWithState(m_stateObject);
return;
}
Contract.Assert(false, "Invalid m_action in Task");
}
您可以在参考源中四处单击以找到您的 CancellationToken
和 action
的路径。
但基本上,构造函数调用一个内部构造函数,该构造函数又调用一个 TaskConstructorCore
,它设置 m_stateObject
和 m_action
(两者都可以在操作时使用被称为)。
InnerInvoke()
由在多个地方调用的方法 Execute()
调用,但您明白了。
我找到了Execute
的路由,它来自执行工作项的线程池。
/// <summary>
/// IThreadPoolWorkItem override, which is the entry function for this task when the TP scheduler decides to run it.
///
/// </summary>
[SecurityCritical]
void IThreadPoolWorkItem.ExecuteWorkItem()
{
ExecuteEntry(false);
}
有趣的是,如果在任务排队之前取消令牌已经取消,则会出现短路。
简介 首先,我已经阅读了以下文章,但我认为它们没有回答这个问题:
Cancellation token in Task constructor: why? What is the use of passing CancellationToken to Task Class constructor?
我很清楚token参数的用途。
我的问题 我尝试用内联注释记录代码,让您了解我在哪里遗漏了所有链接。
代码完成了我想要它做的事情: - 每 2 秒写入一次控制台 - 10 秒后停止
我的问题:"howDoIGetFilled"参数如何获取"token"参数的值。第二个参数用于 Task 实例本身,而不是正在使用的 Action。 如果有任何不清楚的地方,请让我知道你想澄清什么。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TaskDelegatePlayground
{
class Program
{
static void Main(string[] args)
{
var source = new CancellationTokenSource();
var token = source.Token;
Action<object> action = howDoIGetFilled => TestCancellationWithToken((CancellationToken)howDoIGetFilled);
//I understand that this works, as you pass in the token and it gets passed to the "howDoIGetFilled" variable.
//action(token);
//Wrong because it's "hardcoding" the token variable now but I don't understand how the above gets filled in.
//Action<object> action = howDoIGetFilled => TestCancellationWithToken(token);
var task = new Task(action, token);
task.Start();
Thread.Sleep(10000);
//This should cancel the operation
Console.WriteLine("Cancelling");
source.Cancel();
Console.WriteLine("Ended, press any key to close the application.");
Console.ReadKey();
}
public static void TestCancellationWithToken(CancellationToken token)
{
//no intellisense here for token / source
while (true)
{
if (token.IsCancellationRequested)
break;
Console.WriteLine("test");
Thread.Sleep(2000);
}
}
}
}
简答:
当在线程池中调用 Task 时,将执行操作,并且根据它是 Action
还是 Action<T>
,将在有或没有 [=14] 的情况下执行=] 你可以选择传入。
长答案:
正在寻找 Task
的 reference source,这是它被调用的方式:
/// <summary>
/// The actual code which invokes the body of the task. This can be overriden in derived types.
/// </summary>
internal virtual void InnerInvoke()
{
// Invoke the delegate
Contract.Assert(m_action != null, "Null action in InnerInvoke()");
var action = m_action as Action;
if (action != null)
{
action();
return;
}
var actionWithState = m_action as Action<object>;
if (actionWithState != null)
{
actionWithState(m_stateObject);
return;
}
Contract.Assert(false, "Invalid m_action in Task");
}
您可以在参考源中四处单击以找到您的 CancellationToken
和 action
的路径。
但基本上,构造函数调用一个内部构造函数,该构造函数又调用一个 TaskConstructorCore
,它设置 m_stateObject
和 m_action
(两者都可以在操作时使用被称为)。
InnerInvoke()
由在多个地方调用的方法 Execute()
调用,但您明白了。
我找到了Execute
的路由,它来自执行工作项的线程池。
/// <summary>
/// IThreadPoolWorkItem override, which is the entry function for this task when the TP scheduler decides to run it.
///
/// </summary>
[SecurityCritical]
void IThreadPoolWorkItem.ExecuteWorkItem()
{
ExecuteEntry(false);
}
有趣的是,如果在任务排队之前取消令牌已经取消,则会出现短路。