Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.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_Task_Task Parallel Library - Fatal编程技术网

C#暂停异步任务在一种方法中有效,但在另一种方法中无效

C#暂停异步任务在一种方法中有效,但在另一种方法中无效,c#,.net,task,task-parallel-library,C#,.net,Task,Task Parallel Library,我有一个名为PauseOrCancelToken的类,由另一个类PauseOrCancelTokenSource创建。PauseOrCancelToken基本上封装了从MSDN博客文章中实现的CancellationToken和PauseToken: 我已经对它进行了测试,在一个简单的用例示例(我将要发布的代码中的MethodA)中,它按照预期工作 但是,当我使用我打算在生产中使用的非平凡代码(MethodB/ProxyTester.Start())对其进行测试时,它并没有暂停异步任务 publ

我有一个名为PauseOrCancelToken的类,由另一个类PauseOrCancelTokenSource创建。PauseOrCancelToken基本上封装了从MSDN博客文章中实现的CancellationToken和PauseToken:

我已经对它进行了测试,在一个简单的用例示例(我将要发布的代码中的MethodA)中,它按照预期工作

但是,当我使用我打算在生产中使用的非平凡代码(MethodB/ProxyTester.Start())对其进行测试时,它并没有暂停异步任务

public partial class PauseCancelForm : Form
{

    private PauseOrCancelTokenSource pcts = new PauseOrCancelTokenSource();

    public PauseCancelForm()
    {
        InitializeComponent();
    }

    private void StartButton_Click(object sender, EventArgs e)
    {
        Task.Run(() =>
        {
            MethodA(pcts.Token).Wait();
        });
    }

    private async Task MethodA(PauseOrCancelToken pct)
    {
        //Pauses as intended when the pause button is clicked.
        for (int i = 0; i < 10000; i++)
        {
            Console.WriteLine(i);
            await Task.Delay(1000);
            await pct.PauseOrCancelIfRequested();
        }
    }

    private async Task MethodB(PauseOrCancelToken pct)
    {
        //Doesn't pause.
        var proxies = new List<Proxy>();
        var judges = new List<ProxyJudge>();
        for (int i = 0; i < 10000; i++)
        {
            proxies.Add(new Proxy("127.0.0." + RandomUtility.GetRandomInt(1, 100), 8888));
        }

        judges.Add(new ProxyJudge("http://azenv.net"));

        await ProxyTester.Start(proxies, judges, pct);
    }

    private void PauseButton_Click(object sender, EventArgs e)
    {
        pcts.Pause();
    }

    private void StopButton_Click(object sender, EventArgs e)
    {
        pcts.Cancel();
    }

    private void ResumeButton_Click(object sender, EventArgs e)
    {
        pcts.Resume();
    }
}

public class PauseOrCancelTokenSource
{

    private PauseTokenSource pts = new PauseTokenSource();
    private CancellationTokenSource cts = new CancellationTokenSource();
    public PauseOrCancelToken Token { get { return new PauseOrCancelToken(pts, cts); } }

    public void Pause()
    {
        pts.IsPaused = true;
    }

    public void Resume()
    {
        pts.IsPaused = false;
    }

    public void Cancel()
    {
        cts.Cancel();
    }
}

public class PauseOrCancelToken
{
    private PauseToken pt;
    private CancellationToken ct;

    public PauseOrCancelToken(PauseTokenSource pts, CancellationTokenSource cts)
    {
        this.pt = pts.Token;
        this.ct = cts.Token;
    }

    public async Task PauseIfRequested()
    {
        await pt.WaitWhilePausedAsync();
    }

    public void CancelIfRequested()
    {
        ct.ThrowIfCancellationRequested();
    }

    public async Task PauseOrCancelIfRequested()
    {
        await PauseIfRequested();
        CancelIfRequested();
    }
}

public class ProxyTester
{

    public async static Task Start(List<Proxy> proxies, List<ProxyJudge> judges, PauseOrCancelToken pct, List<ProxyTest> tests = null)
    {
        if (tests == null)
        {
            tests = new List<ProxyTest>();
        }

        //Get external IP to check if proxy is anonymous.
        var publicIp = await WebUtility.GetPublicIP();

        //Validate proxy judges.
        var tasks = new List<Task>();
        foreach (var judge in judges)
        {
            tasks.Add(Task.Run(async () => {
                judge.IsValid = await judge.TestValidityAsync();
                await pct.PauseOrCancelIfRequested();
            }));
        }

        await Task.WhenAll(tasks);

        var validJudges = from judge in judges
                            where judge.IsValid
                            select judge;

        if (validJudges.Count() == 0)
        {
            throw new Exception("No valid judges loaded.");
        }

        //Validate proxy tests.
        tasks.Clear();
        foreach (var test in tests)
        {
            tasks.Add(Task.Run(async () => {
                test.IsValid = await test.TestValidityAsync();
                await pct.PauseOrCancelIfRequested();
            }));
        }

        await Task.WhenAll(tasks);

        var validTests = from test in tests
                            where test.IsValid
                            select test;

        var count = 0;
        //Test proxies with a random, valid proxy judge.  If valid, test with all valid proxy tests.
        tasks.Clear();
        foreach (var proxy in proxies)
        {
            tasks.Add(Task.Run(async () =>
            {
                proxy.IsValid = await proxy.TestValidityAsync(validJudges.ElementAt(RandomUtility.GetRandomInt(0, validJudges.Count())));
                count++;
                Console.WriteLine(count);
                await pct.PauseOrCancelIfRequested();

                if (proxy.IsValid)
                {
                    proxy.TestedSites.AddRange(validTests);
                    var childTasks = new List<Task>();
                    foreach (var test in validTests)
                    {
                        childTasks.Add(Task.Run(async () =>
                        {
                            proxy.TestedSites.ElementAt(proxy.TestedSites.IndexOf(test)).IsValid = await proxy.TestValidityAsync(test);
                            await pct.PauseOrCancelIfRequested();
                        }));
                    }

                    await Task.WhenAll(childTasks);
                }
            }));
        }


        await Task.WhenAll(tasks);

    }
}
public分部类PauseCancelForm:Form
{
专用PauseOrCancelTokenSource pcts=新的PauseOrCancelTokenSource();
公共PauseCancelForm()
{
初始化组件();
}
私有无效开始按钮单击(对象发送者,事件参数e)
{
Task.Run(()=>
{
MethodA(pcts.Token.Wait();
});
}
专用异步任务方法A(PauseOrCancelToken pct)
{
//单击“暂停”按钮时按预期暂停。
对于(int i=0;i<10000;i++)
{
控制台写入线(i);
等待任务。延迟(1000);
等待pct.暂停或取消请求();
}
}
专用异步任务方法B(PauseOrCancelToken pct)
{
//没有停顿。
变量代理=新列表();
var法官=新名单();
对于(int i=0;i<10000;i++)
{
添加(新的代理(“127.0.0.”+RandomUtility.GetRandomInt(1100),8888));
}
法官。添加(新的代理法官(“http://azenv.net"));
等待ProxyTester.启动(代理、法官、pct);
}
私有无效暂停按钮单击(对象发送者,事件参数)
{
暂停();
}
私有无效停止按钮\u单击(对象发送者,事件参数e)
{
pcts.Cancel();
}
私有无效恢复按钮\u单击(对象发送者,事件参数e)
{
pcts.Resume();
}
}
公共类PauseOrCancelTokenSource
{
private PauseTokenSource pts=新的PauseTokenSource();
私有CancellationTokenSource cts=新的CancellationTokenSource();
公共PauseOrCancelToken令牌{get{返回新的PauseOrCancelToken(pts,cts);}
公共空间暂停()
{
pts.IsPaused=真;
}
公众简历()
{
pts.IsPaused=假;
}
公开作废取消()
{
cts.Cancel();
}
}
公共类暂停或取消
{
私人波塞特肯私人有限公司;
私有取消令牌ct;
公共PauseOrCancelToken(PauseTokenSource pts、CancellationTokenSource cts)
{
this.pt=pts.Token;
this.ct=cts.Token;
}
公共异步任务PauseIfRequested()
{
wait pt.WaitWhilePausedAsync();
}
public void CancelIfRequested()
{
ct.ThrowIfCancellationRequested();
}
公共异步任务PauseOrCancelIfRequested()
{
等待暂停频率();
取消请求();
}
}
公共类代理测试器
{
公共异步静态任务启动(列表代理、列表判断、PauseOrCancelToken pct、列表测试=null)
{
如果(测试==null)
{
测试=新列表();
}
//获取外部IP以检查代理是否匿名。
var publicIp=wait WebUtility.GetPublicIP();
//验证代理法官。
var tasks=新列表();
foreach(法官中的var法官)
{
tasks.Add(Task.Run)(异步()=>{
judge.IsValid=等待judge.TestValidityAsync();
等待pct.暂停或取消请求();
}));
}
等待任务。何时(任务);
var validJudges=法官中的法官
法官在哪里有效
选择法官;
if(validJudges.Count()==0)
{
抛出新的异常(“未加载有效的法官”);
}
//验证代理测试。
任务。清除();
foreach(测试中的var测试)
{
tasks.Add(Task.Run)(异步()=>{
test.IsValid=wait test.TestValidityAsync();
等待pct.暂停或取消请求();
}));
}
等待任务。何时(任务);
var validTests=来自测试中的测试
test.com在哪里有效
选择测试;
var计数=0;
//使用随机、有效的代理法官测试代理。如果有效,则使用所有有效的代理测试进行测试。
任务。清除();
foreach(代理中的var代理)
{
tasks.Add(Task.Run)(异步()=>
{
proxy.IsValid=wait proxy.testvaliditysync(validJudges.ElementAt(RandomUtility.GetRandomInt(0,validJudges.Count()));
计数++;
控制台写入线(计数);
等待pct.暂停或取消请求();
if(proxy.IsValid)
{
proxy.TestedSites.AddRange(有效测试);
var childTasks=新列表();
foreach(有效测试中的var测试)
{
添加(Task.Run)(异步()=>
{
proxy.TestedSites.ElementAt(proxy.TestedSites.IndexOf(test)).IsValid=wait proxy.testvaliditysync(test);
等待pct.暂停或取消请求();
}));
}
等待任务。WhenAll(子任务);
}
}));
}
等待任务。何时(任务);
}
}

通常,ProxyTester.Start中的代码使用暂停令牌的方式如下:

foreach (var judge in judges)
{
    tasks.Add(Task.Run(async () => {
        judge.IsValid = await judge.TestValidityAsync();
        await pct.PauseOrCancelIfRequested();
    }));
}
这将运行
判断。长度
任务数。暂停令牌时会发生什么?其实没什么用。所有任务都将继续运行,并且所有任务都将完成其有用的工作(
wait judge.testvaliditysync()
)。然后,当所有有用的工作完成时,他们应该刚刚完成-他们将暂停
awa
for (int i = 0; i < 10000; i++)
{
    Console.WriteLine(i);
    await Task.Delay(1000);
    await pct.PauseOrCancelIfRequested();
}