c语言wait 的参数,WaitCallback如何传递ref参数

按照MSDN推荐,线程中如果要传递参数并返回值,可把处理函数及数据封装进类里。

如果要在线程里改变某个主线程变量的值怎么办?

我感觉函数已经封装进类了,没法直接用主线程的全局变量,那就必须使用引用类型把变量传进类里。可这个类如何构造我就不明白了。

我的程序:

class MyProc

{

public void Calc(ref int count)

{

Interlocked.Increment(ref count);

Thread.Sleep(100);

}

}

class testref

{

private int count;

public testref()

{

count = 0;

}

public void test()

{

for (int i = 0; i 

{

Interlocked.Increment(ref count);

MyProc proc = new MyProc();

//就是不知道下一句里的第二个参数怎么构造才能从proc.Calc里引用count

ThreadPool.QueueUserWorkItem(new WaitCallback(proc.Calc), ref count);

}

MessageBox.Show("Count=" + count.ToString());

Thread.Sleep(2000);

MessageBox.Show("Count=" + count.ToString());

}

}

private void button2_Click(object sender, EventArgs e)

{

testref t = new testref();

t.test();

}

7c8003838ad3b03b1cc736f534a35664.png

20分

WaitCallback不能这样用。既然count是testref类的私有变量,那么不应该在其它类对它直接操作。可以改成下面这样:

class MyProc

{

public void Calc(object state)

{

((testref)state).IncreaseCount();

Thread.Sleep(100);

}

}

class testref

{

private int count;

public void test()

{

for (int i = 0; i 

{

IncreaseCount();

MyProc proc = new MyProc();

ThreadPool.QueueUserWorkItem(new WaitCallback(proc.Calc), this);

}

// ...

}

public void IncreaseCount()

{

Interlocked.Increment(ref count);

}

}

或者:

class MyProc

{

public void Calc(object state)

{

((Action)state)();

Thread.Sleep(100);

}

}

class testref

{

private int count;

public void test()

{

for (int i = 0; i 

{

Interlocked.Increment(ref count);

MyProc proc = new MyProc();

ThreadPool.QueueUserWorkItem(new WaitCallback(proc.Calc), new Action(() => Interlocked.Increment(ref count)));

}

// ...

}

}

b829963380d658234a82a0737201a59c.png

引用 楼主 timelight2000 的回复:

按照MSDN推荐,线程中如果要传递参数并返回值,可把处理函数及数据封装进类里。

如果要在线程里改变某个主线程变量的值怎么办?

一个方法要返回值,就可以使用函数返回值规范。而如果其处理实际上可能异步执行,那么就用异步回调方式来返回。

如果不想把大家都搞“死得很难看”,就稍微遵循一点规范。不要瞎写什么 ref。

7c8003838ad3b03b1cc736f534a35664.png

20分

从你堆砌太多的问题代码来看,线程会让你给弄成累赘的。你需要学点简单化、傻瓜化的程序规范。

一个异步(不能保证被同步调用)的方法,它有东西要输出,它要使用委托回调来通知它要输出的结果,例如定义为

public void Calc(int input, Action callback)

这样设计接口!

b829963380d658234a82a0737201a59c.png

我再给你纠正一个、可能是你的老师误导了你的说法,方法

void Calc(ref int x)

{

x = 3;

}

void test()

{

value = 0;

Calc(ref value);

Debug.Assert(value == 3);

}

这能说“方法 Calc 内部把外部变量value给改为3”了吗?如果你老是那样教你,就是非常明显在瞎说了!没有一个正规的说明敢说“ref的意思就是方法内部去修改方法外部的变量值”。如果是你自己瞎猜的,那么情有可原,实际情况完全不是这么回事。ref 的意思是说 Calc 执行结束之后会把结果赋值给 value,而绝不是说 Calc 内部会去修改外部变量 value。

高级语言不胡乱解释什么参数上的 ref 的作用,去掉了c语言的胡乱之源。这是各种高级语言跟 c 的重要区别。

b829963380d658234a82a0737201a59c.png

引用 1 楼 github_22161131 的回复:

class MyProc

{

public void Calc(object state)

{

((Action)state)();

Thread.Sleep(100);

}

}

class testref

{

private int count;

public void test()

{

for (int i = 0; i 

{

Interlocked.Increment(ref count);

MyProc proc = new MyProc();

ThreadPool.QueueUserWorkItem(new WaitCallback(proc.Calc), new Action(() => Interlocked.Increment(ref count)));

}

// ...

}

}

非常感谢。第一种方法顺利执行,不过这第二种生成报错。Action不是具有一个参数的无返回值的函数的委托吗?这个语法好像有些问题啊。但是我不会改,因为感觉这里没有参数啊

b829963380d658234a82a0737201a59c.png

引用 4 楼 sp1234 的回复:

我再给你纠正一个、可能是你的老师误导了你的说法,方法

void Calc(ref int x)

{

x = 3;

}

void test()

{

value = 0;

Calc(ref value);

Debug.Assert(value == 3);

}

这能说“方法 Calc 内部把外部变量value给改为3”了吗?如果你老是那样教你,就是非常明显在瞎说了!没有一个正规的说明敢说“ref的意思就是方法内部去修改方法外部的变量值”。如果是你自己瞎猜的,那么情有可原,实际情况完全不是这么回事。ref 的意思是说 Calc 执行结束之后会把结果赋值给 value,而绝不是说 Calc 内部会去修改外部变量 value。

高级语言不胡乱解释什么参数上的 ref 的作用,去掉了c语言的胡乱之源。这是各种高级语言跟 c 的重要区别。

感谢。我确实把ref理解成C里面的指针了,以为ref就是传了个指针过去,直接操作原来的内存位置呢。

b829963380d658234a82a0737201a59c.png

引用 3 楼 sp1234 的回复:

从你堆砌太多的问题代码来看,线程会让你给弄成累赘的。你需要学点简单化、傻瓜化的程序规范。

一个异步(不能保证被同步调用)的方法,它有东西要输出,它要使用委托回调来通知它要输出的结果,例如定义为

public void Calc(int input, Action callback)

这样设计接口!

我确实没有足够经验,写的东西不规范,诚恳向专家请教。您说的这个道理我明白,但实际过程中是很复杂的。

我要做的东西是这样:testref是我这些功能的封装,每个实例可以做一类这样的工作。在testref里会维护一些myproc对象。testref.test()是每次调用的工作集,会不定时的多次从程序主进程调用;每次调用都会对所有的myproc对象分别调用一次myproc.calc();为了保证速度和主程序响应,所以使用了线程池。对于在testref里面实例化的每一个myproc对象,在myproc构造函数中会传入使其工作必需的参数。calc()执行会有多个结果,分别存在myproc的几个成员里,且其执行效果是累加的。也就是说以前执行的calc的结果会影响下一次执行calc。

我要从testref里随时查看目前执行的结果,这可以通过调用myproc的成员得到。而我要随时知道当前是否有工作正在进行,以便决定能否在testref对象里增加或减少myproc对象,这就需要在testref里保存一个变量count,但要从myproc里去维护它,增加一个线程运行时就+1,线程关闭就-1。这个变量也就是我这次遇到的问题,当然现在在大家帮助下已经能运行了。

但是在这样的目标下,程序结构设置成怎样才是合理的呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值