我想每隔3秒从ip相机中获取一张图像并将其放入Image控件(WPF应用程序)中。
我正在使用此代码:
DispatcherTimer定义
DispatcherTimer dispatcherTimer = new DispatcherTimer(TimeSpan.FromSeconds(3), DispatcherPriority.Background, DispatcherTimer_Tick, Application.Current.Dispatcher);
图片抓取代码
private void DispatcherTimer_Tick(object sender, EventArgs evA)
{
Dispatcher.Invoke(DispatcherPriority.Background,
new Action(() =>
{
try
{
BitmapFrame src;
var webRequest = (HttpWebRequest)WebRequest.Create(@"http://camera_ip/cgi-bin/video.cgi?msubmenu=jpg");
webRequest.Credentials = new NetworkCredential("user", "password");
webRequest.Proxy = null;
var response = (HttpWebResponse)webRequest.GetResponse();
var stream = response.GetResponseStream();
var streamReader = new StreamReader(stream);
src = BitmapFrame.Create(streamReader.BaseStream);
imageTelecamera.BeginInit();
imageTelecamera.Source = src;
imageTelecamera.EndInit();
}
catch (Exception ex)
{
DoLogD($"Error: {ex.Message}");
}
}
));
}
它工作正常但是当我抓取图像时,UI会冻结几毫秒。
为什么调度员在不影响用户界面的情况下不在后台工作?
答案 0 :(得分:0)
你误解了调度员是什么
调度程序允许您将命令发送到GUI线程,这意味着当您的命令执行时,GUI线程暂停等待它完成。
正确使用Dispatcher是将线程特定任务发送到正确的线程来执行它们,即你的控件有一个子列表,列表只能从控件安全地编辑,所以如果你需要添加或删除一个child使用控件Dispatcher来获取控件以执行添加新的Item命令
这是一个完整的例子
<强> XAML:强>
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<Button x:Name="butStart" DockPanel.Dock="Top" Click="Button_Click">start</Button>
<TextBlock x:Name="output"/>
</DockPanel>
</Window>
代码背后:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
timer.Interval = new TimeSpan(0, 0, 3);
timer.Tick += Timer_Tick;
}
private void Timer_Tick(object sender, EventArgs e)
{
//start taking photo
Task.Run(()=> TakePhoto() );
}
public DispatcherTimer timer { get; } = new DispatcherTimer();
private void Button_Click(object sender, RoutedEventArgs e)
{
if(timer.IsEnabled)
{
timer.Stop();
butStart.Content = "Start";
//this works as you are in the main thread
output.Text += "Time Stopped" + Environment.NewLine;
}
else
{
timer.Start();
butStart.Content = "Stop";
output.Text += "Time Started" + Environment.NewLine;
}
}
public async void TakePhoto()
{
//with out the dispatcher this would error as you are not in the Gui thread so have no access to the Text property
output.Dispatcher.Invoke(()=>output.Text += "Take Photo" + Environment.NewLine);
//Simulate a long running task
await Task.Delay(5000);
output.Dispatcher.Invoke(()=>output.Text += "Take Photo - Complete" + Environment.NewLine);
}
}
现已应用于您的代码
private void DispatcherTimer_Tick(object sender, EventArgs evA)
{
Task.Run() =>
{
try
{
BitmapFrame src;
var webRequest = (HttpWebRequest)WebRequest.Create(@"http://camera_ip/cgi-bin/video.cgi?msubmenu=jpg");
webRequest.Credentials = new NetworkCredential("user", "password");
webRequest.Proxy = null;
var response = (HttpWebResponse)webRequest.GetResponse();
var stream = response.GetResponseStream();
var streamReader = new StreamReader(stream);
src = BitmapFrame.Create(streamReader.BaseStream);
imageTelecamera.Dispatcher.Invoke(()=>
{
imageTelecamera.BeginInit();//not actually required
imageTelecamera.Source = src;
imageTelecamera.EndInit();//not actually required
});
}
catch (Exception ex)
{
DoLogD($"Error: {ex.Message}");
}
}
));
}