Re: [问题] Thread被咬住如何解决?

楼主: fo40225   2015-07-28 23:10:39
尝试写一个比较简单好理解的版本
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
tabControl1.SelectedIndex = 1;
var task = Task.Run(() =>
{
DateTime DateTime1 = DateTime.Now;
TimeSpan ts1 = new TimeSpan(DateTime1.Ticks);
DateTime DateTime2;
TimeSpan ts2;
TimeSpan ts = new TimeSpan();
while (progressBar1.Value < progressBar1.Maximum)
{
DateTime2 = DateTime.Now;
ts2 = new TimeSpan(DateTime2.Ticks);
ts = ts1.Subtract(ts2).Duration();
this.Invoke((Action)(() =>
progressBar1.Value = Convert.ToInt32((ts.TotalSeconds / 1.5) * 100)));
}
//PASS Color 128,255,128 Green
this.Invoke((Action)(() =>
label1.BackColor = Color.FromArgb(128, 255, 128)));
this.Invoke((Action)(() =>
label1.ForeColor = Color.Green));
MessageBox.Show(ts.TotalSeconds.ToString());
});
await task;
}
}
: 2.为什么里面这个async可以直接加上“()”和“=>”这些符号
: 还有它们的作用是什么?
这是lambda表示式 代表一个匿名函式 如果不使用lambda 另外写具名方法也可以
请参考
https://msdn.microsoft.com/zh-tw/library/bb397687
: 【2】
: _CurrentContext.Post(new SendOrPostCallback((_) => {...}), null);
: 这段....老实说....有点....超出理解范围 |||"orz
: 但是连查了MSDN都看不懂它们要怎么使用 爬Google也几乎找不到相关资料
: 希望能有详细一点的解释还有符号的说明 真是不好意思 OAQ
这个超出新手范围 你应该要知道的是 在WinForm程式中 非UI执行绪不能更新UI
所以必须将你想要更新UI的方法想办法传给UI执行绪
singledream 是将UI执行绪的上下文记起来 然后将更新的方法Post过去
注意看我程式码红字的地方 我一样将一个方法(是一个lambda匿名函式)
传入this(form1)的Invoke方法 这个方法会在UI执行绪上执行你指定的方法
: 目前可以看得出来的地方是 不会卡住CPU的地方直接写出来
: 可能会咬死的地方则是用async跟await制造出另一个thread
: 虽然直接看完成的程式可以得到这个结论
: 但是里面的语法跟设计期间的逻辑却还是有点不懂
: 换句话说就是如果要从零开始重新coding的话很可能会想不到该怎么做
async await 背后是 ThreadPool 不一定会有新的执行绪
产生一个新的Task就是把你的方法放到排程里
runtime会调度ThreadPool帮你把Task完成
简单的想法就是把await看成是会存盘的return
当Task完成后 会接着await之后继续做
不一定是原来的执行绪 只有winform会是同一个
因为背后偷偷帮你用了SynchronizationContext
可以试着在winform与console中执行下面的范例
private async void button1_Click(object sender, EventArgs e)
{
M1();
await Task.Delay(1000);
M2();
}
private void M1()
{
MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
}
private void M2()
{
MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
}
console
internal class Program
{
static void Main(string[] args)
{
Program.MainAsync().Wait();
}
private static async Task MainAsync()
{
Program.M1();
await Task.Delay(1000);
Program.M2();
}
private static void M1()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
}
private static void M2()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
}
}
async await 更多请参考
https://msdn.microsoft.com/zh-tw/library/hh191443
由于 async await 是基于Task的 最好先搞懂TPL 会比较好懂
https://msdn.microsoft.com/zh-tw/library/dd537609
: 另外 推文也有提到说“一直去频繁更新UI也是不好的”
: 那应该怎么做才对?
: 除了不断地去更新它 我实在想不到什么比较好的办法 |||"orz
可以设定Timer 由UI去问进度 或是Task一段时间回报进度再更新UI都可以
※ 引述《pthuang (◢晓筱◤)》之铭言:
: 希望有人或是fo40225可以帮我解个惑 谢谢 m(_ _)m
作者: singledream (鱼大头)   2015-07-31 00:36:00
有些解释好像比较让人浅显易懂,谢谢版友分享

Links booklink

Contact Us: admin [ a t ] ucptt.com