C# 从listview创建和停止线程

C# 从listview创建和停止线程,c#,multithreading,C#,Multithreading,我需要您的帮助,对于线程,我已满0,您只需要创建一个特定线程并在命令下完成它,但我不会提前创建每个线程,因为会有很多线程,我是这样做的: Thread thread = new Thread(() => Go(..... many many variables that are taken from the listview ......)); thread.Start(); 因此,如上所述,变量取自listview,我从文件中加载listview,然后运行所需的线程。但是流中的进程是无

我需要您的帮助,对于线程,我已满0,您只需要创建一个特定线程并在命令下完成它,但我不会提前创建每个线程,因为会有很多线程,我是这样做的:

Thread thread = new Thread(() => Go(..... many many variables that are taken from the listview ......));
thread.Start();
因此,如上所述,变量取自listview,我从文件中加载listview,然后运行所需的线程。但是流中的进程是无限的,只有当我完全关闭程序时才会结束,并且我希望以与启动流相同的方式结束流(右键单击所需的行start/stop)。正如我所说的,我从来没有使用过线程,我认为这很简单,比如当你开始一个线程时,你给它分配了一个ID,然后用相同的ID结束它,但是唉。我在谷歌上搜索了很多次,没有找到一个适合我的例子(我将第三次重复——我从来没有使用过线程,我不需要说“去阅读关于TPL的文章”),所以我请求帮助,最好是举个例子)


我有一个非常糟糕的想法:在工作表中有一个不可见的列,其中一个id在开始时生成,然后当我发送一个命令来启动线程时,会创建一个名为int id1=0的唯一变量,它的名称会传递给线程本身,每次循环启动时,id1=0或1会分别在其中被选中,如果0-继续,如果1-空。那么,当你点击停止按钮时,它的值变为1是合乎逻辑的。但在我看来,当线程变成100+时,多线程的圣灵会因此惩罚我。我在某个地方读到过这个想法,所以不要发誓)

你不需要数百条线程来完成这个任务。您的工作线程正在执行HTTP请求,这可以在不需要新线程的情况下异步完成。此外,除非您有数百个CPU内核(您没有),否则数百个线程也不会真正帮助您

对于这类工作,我建议如下:

  • 编写一个方法来完成线程所做的所有工作,同时在每次迭代中检查
    CancellationToken

  • 在循环中调用该方法,每个帐户调用一次,并将生成的任务存储在数组或列表中。或者使用LINQ(正如我在本例中所做的)创建列表

  • 当程序终止时,激活
    取消令牌

  • 取消后,您必须等待所有任务,以便观察任何可能的异常并干净地退出

  • 比如说

    public async Task DoTheWork(Account account, CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            var result = await httpClient.GetAsync(account.Url);
            await DoSomethingWithResult(result);
            await Task.Delay(1000);
        }
    }
    
    //Main program
    var accounts = GetAccountList();
    var source = new CancellationTokenSource();
    var tasks = accounts.Select( x => DoTheWork(x, source.Token) ).ToList();
    
    
    //When exiting
    source.Cancel();
    await Task.WhenAll( tasks );
    source.Dispose();    
    
    个别取消 下面是另一种方法,它保存一个帐户列表和一个可用于取消该特定帐户任务的委托

    //Declare this somewhere it will persist for the duration of the program
    //The key to this dictionary is the account you wish to cancel
    //The value is a delegate that you can call to cancel its task
    Dictionary<Account, Func<Task>> _tasks = new Dictionary<Account, Func<Task>>();
    
    async Task CreateTasks()
    {
        var accounts = GetAccounts();
        foreach (var account in accounts)
        {
            var source = new CancellationTokenSource();
            var task = DoTheWork(account, source.Token);
            _tasks.Add(account, () => { source.Cancel(); return task; });
        }
    }
    
    //Retrieve the delegate from the dictionary and call it to cancel its task
    //Then await the task to observe any exceptions
    //Then remove it from the list
    async Task CancelTask(Account account)
    {
        var cancelAction = _tasks[account];
        var task = cancelAction();
        await task;
        _tasks.Remove(account);
    }
    
    async Task CancelAllTasks()
    {
        var tasks = _tasks.Select(x => x.Value()).ToList();
        await Task.WhenAll(tasks);
    }
        
    
    //在某个地方声明它将在程序执行期间保持不变
    //此词典的密钥是您要取消的帐户
    //该值是可以调用以取消其任务的委托
    字典_tasks=新字典();
    异步任务CreateTasks()
    {
    var accounts=GetAccounts();
    foreach(账户中的var账户)
    {
    var source=新的CancellationTokenSource();
    var task=DoTheWork(account,source.Token);
    _添加(帐户,()=>{source.Cancel();返回任务;});
    }
    }
    //从字典中检索委托并调用它以取消其任务
    //然后等待任务观察任何异常
    //然后将其从列表中删除
    异步任务取消任务(帐户)
    {
    var cancelAction=_任务[帐户];
    var task=cancelAction();
    等待任务;
    _任务。删除(帐户);
    }
    异步任务CancelAllTasks()
    {
    var tasks=_tasks.Select(x=>x.Value()).ToList();
    等待任务。何时(任务);
    }
    
    此操作不需要数百个线程。您的工作线程正在执行HTTP请求,这可以在不需要新线程的情况下异步完成。此外,除非您有数百个CPU内核(您没有),否则数百个线程也不会真正帮助您

    对于这类工作,我建议如下:

  • 编写一个方法来完成线程所做的所有工作,同时在每次迭代中检查
    CancellationToken

  • 在循环中调用该方法,每个帐户调用一次,并将生成的任务存储在数组或列表中。或者使用LINQ(正如我在本例中所做的)创建列表

  • 当程序终止时,激活
    取消令牌

  • 取消后,您必须等待所有任务,以便观察任何可能的异常并干净地退出

  • 比如说

    public async Task DoTheWork(Account account, CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            var result = await httpClient.GetAsync(account.Url);
            await DoSomethingWithResult(result);
            await Task.Delay(1000);
        }
    }
    
    //Main program
    var accounts = GetAccountList();
    var source = new CancellationTokenSource();
    var tasks = accounts.Select( x => DoTheWork(x, source.Token) ).ToList();
    
    
    //When exiting
    source.Cancel();
    await Task.WhenAll( tasks );
    source.Dispose();    
    
    个别取消 下面是另一种方法,它保存一个帐户列表和一个可用于取消该特定帐户任务的委托

    //Declare this somewhere it will persist for the duration of the program
    //The key to this dictionary is the account you wish to cancel
    //The value is a delegate that you can call to cancel its task
    Dictionary<Account, Func<Task>> _tasks = new Dictionary<Account, Func<Task>>();
    
    async Task CreateTasks()
    {
        var accounts = GetAccounts();
        foreach (var account in accounts)
        {
            var source = new CancellationTokenSource();
            var task = DoTheWork(account, source.Token);
            _tasks.Add(account, () => { source.Cancel(); return task; });
        }
    }
    
    //Retrieve the delegate from the dictionary and call it to cancel its task
    //Then await the task to observe any exceptions
    //Then remove it from the list
    async Task CancelTask(Account account)
    {
        var cancelAction = _tasks[account];
        var task = cancelAction();
        await task;
        _tasks.Remove(account);
    }
    
    async Task CancelAllTasks()
    {
        var tasks = _tasks.Select(x => x.Value()).ToList();
        await Task.WhenAll(tasks);
    }
        
    
    //在某个地方声明它将在程序执行期间保持不变
    //此词典的密钥是您要取消的帐户
    //该值是可以调用以取消其任务的委托
    字典_tasks=新字典();
    异步任务CreateTasks()
    {
    var accounts=GetAccounts();
    foreach(账户中的var账户)
    {
    var source=新的CancellationTokenSource();
    var task=DoTheWork(account,source.Token);
    _添加(帐户,()=>{source.Cancel();返回任务;});
    }
    }
    //从字典中检索委托并调用它以取消其任务
    //然后等待任务观察任何异常
    //然后将其从列表中删除
    异步任务取消任务(帐户)
    {
    var cancelAction=_任务[帐户];
    var task=cancelAction();
    等待任务;
    _任务。删除(帐户);
    }
    异步任务CancelAllTasks()
    {
    var tasks=_tasks.Select(x=>x.Value()).ToList();
    等待任务。何时(任务);
    }
    
    在现代c#中,您可能不应该直接使用线程(除非您是非常高级的开发人员,并且有令人信服的理由)。还有许多其他语言功能可用于处理多个任务,例如
    异步任务
    、TPL和