C# 如何在C中使用ThreadPool调用带参数的函数#

C# 如何在C中使用ThreadPool调用带参数的函数#,c#,function,threadpool,C#,Function,Threadpool,根据另一篇文章中的建议,我已经能够为一个使用多线程和 有一个开始按钮和一个停止按钮。“开始”按钮调用一个需要几分钟才能完成的函数。只要我想,停止按钮就会停止函数的执行 这段代码与没有参数的SlowFunction()完美结合,但我的实际函数需要一个字符串 参数起作用,定义如下: public void SlowFunction(string str) {...} 然后,我的问题是无法使用“WaitCallback(…)”部分中的参数调用函数 在这段代码中,因为SlowFunction()没有参

根据另一篇文章中的建议,我已经能够为一个使用多线程和 有一个开始按钮和一个停止按钮。“开始”按钮调用一个需要几分钟才能完成的函数。只要我想,停止按钮就会停止函数的执行

这段代码与没有参数的SlowFunction()完美结合,但我的实际函数需要一个字符串 参数起作用,定义如下:

public void SlowFunction(string str) {...}
然后,我的问题是无法使用“WaitCallback(…)”部分中的参数调用函数

在这段代码中,因为SlowFunction()没有参数,所以没有问题,我可以这样调用函数

ThreadPool.QueueUserWorkItem(new WaitCallback(SlowFunction), cts.Token);
但是如果不使用不需要参数的SlowFunction(),而是使用需要强制字符串参数的新SlowFunction1(Somestring)

    public void SlowFunction1(string sec)
    {
        double sec1 = Convert.ToDouble(sec);
        var end = DateTime.Now + TimeSpan.FromSeconds(sec1);
        while (DateTime.Now < end)
        { }
        MessageBox.Show("Process finished1");
    } 
如何使用WaitCallback()调用带参数的SlowFunction1? 如何修改SlowFunction 1的定义?我已经尝试了下面的方法,但不起作用

    public void SlowFunction(string str, object obj)
    {
        CancellationToken token = (CancellationToken)obj;
        ..
    }
下面是我目前正在使用的不需要参数的SlowFunction代码。谢谢你的帮助

namespace SampleStartStop
{    
    public partial class Form1 : Form
    {       
        // Create the token source.
        CancellationTokenSource cts = new CancellationTokenSource();

        public Form1()
        {
            InitializeComponent();            
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }           
            cts = new CancellationTokenSource();
            ThreadPool.QueueUserWorkItem(new WaitCallback(SlowFunction), cts.Token);                         
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
                cts = null;
                MessageBox.Show("Processing cancelled");
            }   
        }
        public void SlowFunction(object obj)
        {
            CancellationToken token = (CancellationToken)obj;

            var end = DateTime.Now + TimeSpan.FromSeconds(4);
            while (DateTime.Now < end)
            {
                if (token.IsCancellationRequested)
                {                
                    break;
                }
            }
            if (!token.IsCancellationRequested)
            {
                MessageBox.Show("Processing finished");
            }
        }

    }
}
名称空间SampleStartStop
{    
公共部分类Form1:Form
{       
//创建令牌源。
CancellationTokenSource cts=新的CancellationTokenSource();
公共表格1()
{
初始化组件();
}
私有void btnStart_单击(对象发送方,事件参数e)
{
如果(cts!=null)
{
cts.Cancel();
}           
cts=新的CancellationTokenSource();
ThreadPool.QueueUserWorkItem(新的WaitCallback(SlowFunction),cts.Token);
}
私有void btnStop_单击(对象发送方,事件参数e)
{
如果(cts!=null)
{
cts.Cancel();
cts=null;
MessageBox.Show(“处理已取消”);
}   
}
公共无效慢函数(对象obj)
{
CancellationToken=(CancellationToken)obj;
var end=DateTime.Now+TimeSpan.FromSeconds(4);
while(DateTime.Now
有很多方法可以做到这一点,下面是一些方法:

1使用
state
参数传递单个变量

void Method1( object state )
{
    var sec = (string)state;
    // use sec here
}

// call this using
ThreadPool.QueueUserWorkItem( Method1, "20" );
2使用
state
参数传递包含多个变量的对象

class Foo
{
    public string Seconds { get; set; }
    public int OtherStuff { get; set; }
}

void Method2( object state )
{
    var args = (Foo)state;          
    // use args.Seconds and args.OtherStuff here
}

// call this like so:
var args = new Foo()
{
    Seconds = "20",
    OtherStuff = 4711
};

ThreadPool.QueueUserWorkItem( Method2, args );
3创建一个包含变量和代码的worker类

class Worker
{
    public string Seconds { get; set; }
    public int OtherStuff { get; set; }

    public void DoWork( object unused )
    {
        // use this.Seconds and this.OtherStuff here
    }
}

// call like so:
var worker = new Worker()
{
    Seconds = "20",
    OtherStuff = 4711
};

ThreadPool.QueueUserWorkItem( worker.DoWork );
4使用匿名委托

string sec = "20";

ThreadPool.QueueUserWorkItem( delegate
                              {
                                  // use sec here            
                              } );   

很明显,您正在使用.Net4.0或更高版本。没有理由直接使用
ThreadPool.Queue…
。使用时,它提供了许多有用的功能

解决这个问题的简单方法是使用lambda表达式

private void btnStart_Click(object sender, EventArgs e)
{
    if (cts != null)
    {
        cts.Cancel();
    }           
    cts = new CancellationTokenSource();
    Task.Factory.StartNew(()=> SlowFunction(SomeString, cts.Token), cts.Token, TaskCreationOptions.None, TaskScheduler.Default);                       
}

public void SlowFunction(string str, CancellationToken token)
{
    //Your code
}
请注意,您不再需要将
CancellationToken
作为
对象键入。它可以是强类型的


也要知道。如果您在.Net4.5中,请使用
Task.Run
,否则请明确指定
TaskScheduler

我们真的需要这些粗体标题吗?它只是增加了噪音。不,我想它们确实有点太大胆了,呵呵。你好,克里斯,谢谢你分享这4种方法,我仍然不太清楚如何使用它们。我是否应该在您放置的注释行中插入对函数的调用?而不是使用字符串,而是使用这个.seconds?请您给我举一个更详细的例子,说明如何与代表pleaseHi Sriram相处,谢谢您的帮助。我能够实现您的解决方案,它与StarNew和Task.Run一起工作。非常感谢。
private void btnStart_Click(object sender, EventArgs e)
{
    if (cts != null)
    {
        cts.Cancel();
    }           
    cts = new CancellationTokenSource();
    Task.Factory.StartNew(()=> SlowFunction(SomeString, cts.Token), cts.Token, TaskCreationOptions.None, TaskScheduler.Default);                       
}

public void SlowFunction(string str, CancellationToken token)
{
    //Your code
}