c#多线程耗时操作不卡界面的顺序流程处理方式
By
admin
at 2021-01-06 • 0人收藏 • 1576人看过
这里新建了method.cs类库, 在类库中需要实时更新数据输出到form1界面中的lable1控件上面 , 我们需要在界面form1中调用此类库, 来执行一个耗时流程.
我们知道在c#里为了不卡界面就需要开多线程 , 多线程里想要更新界面UI控件就需要用到委托 , 看了一些文章发现写的基本千篇一律, 都是在同一个form界面中进行的委托定义和使用, 实际使用中却并不如此, 像我上面的需求, 那么在method类中应该怎么处理才能最简单直接呢?
经过了多次测试, 我发现下面的写法应该是最直观和简单的办法.
我在method中定义一个委托函数, 在form1界面中将这个函数给赋值, 代码如下:
method.cs代码如下:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace WindowsFormsApp2
{
internal class Method
{
//定义一个全局委托函数
public static Action<string> WriteStr;
//手动停止
public static bool HandStop { get; set; }
//耗时函数实例
public static bool demoFunc()
{
var FindOK = false;
var tsk = Task.Run(() => {
for (int i = 0; i < 100; i++)
{
WriteStr(i.ToString());
if (HandStop)
{
FindOK = false;
break;
}
if (i>40)
{
FindOK = true;
break;
}
Thread.Sleep(100);
}
});
tsk.Wait();
return FindOK;
}
}
} form1.cs界面代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
Method.HandStop = false;
//方式一: 先定义,再使用
//Action<string> action1 = (str) =>
//{
// Action action = () =>
// {
// label1.Text = str;
// };
// this.BeginInvoke(action);
//};
//Method.WriteStr = action1;
//方式二: 直接赋值定义使用
Method.WriteStr = (str) =>
{
Action action = () =>
{
label1.Text = str;
};
this.BeginInvoke( action );
};
//任务内部会自动调用上面的委托
var tsk = Task.Run(() =>
{
var ret = Method.demoFunc( ) ;
});
//等待任务完成
await tsk;
Console.WriteLine("ok");
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Method.HandStop = true;
}
private void button3_Click(object sender, EventArgs e)
{
Method.HandStop = true;
}
}
}代码工程如下:
开线程无限刷新界面实例:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
//全局定义
Action<string> loopStr;
public Form1()
{
InitializeComponent();
//函数初始化
loopStr = (str) =>
{
Action action = () =>
{
label2.Text = str;
};
this.BeginInvoke(action);
};
}
private void Form1_Load(object sender, EventArgs e)
{
Method.HandStop = false;
Task.Run(() =>
{
var i = 0;
while (!Method.HandStop)
{
//调用
loopStr(i.ToString());
Thread.Sleep(100);
i++;
}
Console.WriteLine("loop end");
});
}
private void button3_Click(object sender, EventArgs e)
{
Method.HandStop = true;
}
}
}using System;
using System.Threading;
using System.Threading.Tasks;
namespace WindowsFormsApp2
{
internal class Method
{
//定义一个全局委托函数
public static Action<string> WriteStr;
//手动停止
public static bool HandStop { get; set; }
//耗时函数实例
public static bool demoFunc()
{
var FindOK = false;
var tsk = Task.Run(() => {
for (int i = 0; i < 100; i++)
{
WriteStr(i.ToString());
if (HandStop)
{
FindOK = false;
break;
}
if (i>40)
{
FindOK = true;
break;
}
Thread.Sleep(100);
}
});
tsk.Wait();
return FindOK;
}
}
}C#调用dll方法
//第一步,添加dll运行库
using System.Runtime.InteropServices;
//第二步,
[DllImport("Demo.dll", EntryPoint = "demo_init", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern UInt16 demo_init();
[DllImport("Demo.dll", EntryPoint = "demo_read_inbit", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern Int32 demo_read_inbit(UInt16 cardno, UInt16 bitno);
3 个回复 | 最后更新于 2024-03-02
登录后方可回帖
public async void HeadTailClick(Button bt, Action tsk) { var preColor = bt.BackColor; bt.BackColor = Color.Chocolate; bt.Enabled = false; //await Task.Run(tsk).ConfigureAwait(false); await Task.Factory.StartNew(tsk, TaskCreationOptions.LongRunning).ConfigureAwait(false); bt.Enabled = true; bt.BackColor = preColor; } private void button12_Click(object sender, EventArgs e) { HeadTailClick((Button)sender, () => { var axis = (ushort)GLoableVar.AxisNum.L; USBMove.setAxisSpeed(axis, 30000); var pos = double.Parse(PicIni.GetKeyValue("镜头位置", "芯片左", USBMove.getPos(axis).ToString())); USBMove.pMoveAbs(axis, pos); USBMove.waitStop(axis); //切换轴 rb_left.PerformClick(); }); }