目的:介绍在WPF下C#多线程的应用,针对从MFC转向C#开发的过程中,两者在多线程中的不同进行。本文不是详细的多线程应用总结,而是强调快速应用,因此,一般的多线程相关概念请自行Google之。
从MFC到C#的多线程一般存在以下疑惑:
1、线程如何创建?
2、线程如何控制?
3、主界面如何更新?
先讲第一个问题:线程如何创建?
C#下创建多线程由类Thread来完成,先看其构造函数:
ThreadStart 和 ParameterThreadStart
参数都是委托,所以可以看出委托其实就是方法的抽象,前者用于不带参数的并且无返回值的
方法的抽象 ,后者是带object参数的方法的抽象 ,大家通过以下简单的方法注意下线程如何调用带参数的方法
实例如下:
public class ThreadStartTest
{
//无参数的构造函数
Thread thread = new Thread(new
ThreadStart(ThreadMethod));
//带有object参数的构造函数
Thread thread2 = new Thread(new
ParameterizedThreadStart(ThreadMethodWithPara));
public ThreadStartTest()
{
//启动线程1
thread.Start();
//启动线程2
thread2.Start(new Parameter { paraName="Test" });
}
static void
ThreadMethod()
{
//....
}
static void ThreadMethodWithPara(object
o)
{
if (o is
Parameter)
{
// (o as
Parameter).paraName.............
}
}
}
public class
Parameter
{
public string paraName { get; set; }
}
不带参数的方法似乎很简单的能被调用,只要通过第一个构造函数便行,对于带参数的方法,大家注意下参数是如何传入线程所调用的方法, 当启动线程时, 参数通过thread.Start方法传入 ,于是我们便成功启动了thread线程
第二个问题:线程如何控制?
Thread.start();Thread.sleep();Thread.... 等
第三个问题:主界面如何更新?
这个问题是学习过程中的主要问题点。下面具体谈谈。
CLR下每个线程创建的控件只能由所创建的线程控制,其他线程进行修改将会出错。
WPF下界面由UI线程创建并控制,从线程安全的角度来说,其他线程要更新UI界面,都需要通过UI线程来更新。如何进行呢?通过委托,即我(另一线程)要更新UI线程的控件,我不能自己修改,我得委托主人家去修改。背后应该也是通过消息的机制来完成的。
this.Dispatcher.BeginInvoke((Action)delegate()
{
hWindowControl.HalconWindow.DispObj(hImage);
});
下面是一个完整的例子,通过多线程控制大恒相机进行采集图像并显示,基于Halcon进行显示。需安装Halcon10及以上版本,同时引用其控件
CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using HalconDotNet;
using System.Threading;
using System.Windows.Threading;
using USBCamera;
using USBCameraAPI = USBCamera.API;
using USBCameraSample;
namespace multiThread_snap
{
///
/// Interaction logic for
MainWindow.xaml
///
public partial class
MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
m_Camera.Initialize();
hImage =
new HImage();
}
private void snap_Click(object sender,
RoutedEventArgs e)
{
ThreadStart dethreadst = new
ThreadStart(Snap);
Thread thread= new
Thread(dethreadst);
thread.Start();
}
private USBCameraSample.USBCameraSample m_Camera
= new USBCameraSample.USBCameraSample();
private void Window_Closed(object sender,
EventArgs e)
{
m_Camera.Release();
}
private void Snap()
{
IntPtr[]
buffers = new IntPtr[1];
buffers[0]
= m_Camera.GetRawBuffer();
HVSTATUS
status = USBCameraAPI.HVSnapShot(m_Camera.GetHandle(), buffers,
1);
hWindowControl.HalconWindow.SetPart(0, 0, 2592, 1944);
hImage.GenImage1("byte", 2592, 1944,
m_Camera.GetRawBuffer());
this.Dispatcher.BeginInvoke((Action)delegate()
{
hWindowControl.HalconWindow.DispObj(hImage);
});
}
private HImage hImage;
private void Window_Loaded(object sender,
RoutedEventArgs e)
{
}
private void redKey_Click(object sender,
RoutedEventArgs e)
{
disp.Fill
= Brushes.Red;
}
private void greenKey_Click(object sender,
RoutedEventArgs e)
{
disp.Fill
= Brushes.Green;
}
}
}//namespace
XAML:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="768"
Width="1024"
xmlns:my="clr-namespace:HalconDotNet;assembly=halcondotnet"
WindowStartupLocation="CenterScreen"
Closed="Window_Closed"
Loaded="Window_Loaded">
Content="采集"
Height="35"
HorizontalAlignment="Left"
Margin="51,24,0,0"
Name="snap"
VerticalAlignment="Top"
Width="81"
Click="snap_Click" />
Height="484"
HorizontalAlignment="Left"
Margin="184,37,0,0"
Name="hWindowControl"
VerticalAlignment="Top"
Width="754" />
Height="30"
HorizontalAlignment="Left"
Margin="68,114,0,0"
Name="disp"
Stroke="Black"
VerticalAlignment="Top"
Width="30"
Fill="Red"
/>
Content="红"
Height="26"
HorizontalAlignment="Left"
Margin="38,191,0,0"
Name="redKey"
VerticalAlignment="Top"
Width="59"
Click="redKey_Click" />
Content="绿"
Height="24"
HorizontalAlignment="Left"