我正在开发一个与服务器通信的应用程序。
thread = new Thread(new ThreadStart(ClientStart));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
private void ClientStart()
{
tcpClient = new TcpClient(ip,3000);
stream = tcpClient.GetStream();
while (true) {
stream.Read(...);
PrintMessage(...);
.....
}
}
private void PrintMessage(LogWin w, string msg)
{
DateTime dt = DateTime.Now;
w.GetMessageBox().Dispatcher.BeginInvoke(DispatcherPriority.Input,new Action(()=>w.GetMessageBox()
.AppendText(String.Format("{0:d/M/yyyy HH:mm:ss}", dt) + " : " + msg)));
}
Run Code Online (Sandbox Code Playgroud)
稍后我需要将结果打印到消息框。我知道我必须使用 Dispatcher,因为我在另一个线程中工作,但是即使我使用 beginInvoke 方法,我的应用程序也会冻结。
根据谢里丹的回答进行编辑:
现在我得到:WindowsBase.dll 中发生类型为“System.InvalidOperationException”的未处理异常
附加信息:调用线程无法访问此对象,因为其他线程拥有它。
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
thread = new Thread(() => ClientStart(dispatcher));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
private void ClientStart(Dispatcher dispatcher)
{
....
Run Code Online (Sandbox Code Playgroud)
并更改了打印方法:
dispatcher.BeginInvoke(DispatcherPriority.Input, new …Run Code Online (Sandbox Code Playgroud) 我试图将调度程序包装在一个线程中.但结果并不是我所期待的.我该如何解决这个问题?
public void Start()
{
ThreadStart ts = inner;
Thread wrapper = new Thread(ts);
wrapper.Start();
}
private void inner()
{
_Runner.Dispatcher.Invoke(_Runner.Action, DispatcherPriority.Normal);
}
Run Code Online (Sandbox Code Playgroud) 我在Silverlight代码隐藏中有一段代码看起来像这样:
foreach (MapLocation loc in e.Result)
{
testDict[loc.ElemId] = loc.ToString();
this.Dispatcher.BeginInvoke(delegate()
{
Image icon = new Image();
icon.SetValue(Image.SourceProperty, nurseIconSource);
Canvas.SetLeft(icon, (double)loc.X * MAP_SCALE);
Canvas.SetTop(icon, MAP_HEIGHT - (double)loc.Y * MAP_SCALE);
icons[loc.ElemId] = icon;
MainCanvas.Children.Add(icon);
});
}
}
Run Code Online (Sandbox Code Playgroud)
此循环在与UI线程分开的线程上运行25次.执行该方法后,testDict对象以所有25个条目结束,而图标字典仅存储第25个(最后一个)项目的条目.
这是我第一次使用Dispatcher.它不是故意被称为快速射击吗?我能想到的是,第一次调用委托是在最后一次循环之后,因此loc对象始终是同一个项目.这准确吗?
我通常Dispatcher.Invoke在需要从后台线程访问一些UI元素时使用.最近我不得不改变其他人的书面资料,我看到他完成的相同任务,如:
Dispatcher.Invoke((ThreadStart)delegate
{
//some code that uses controls from UI
});
Run Code Online (Sandbox Code Playgroud)
我什么时候应该使用这样的代码而不是Dispatcher.Invoke/BeginInvoke为什么?
我有日志拖尾应用程序,它在不定式循环中执行后台工作程序线程并检查某些TXT文件中的最新条目.一旦找到新条目,我使用Dispatcher.Invoke更新屏幕上的TextBox,并将最新条目添加到文本文件中.
问题是,如果源文本文件每毫秒不断更新,用户界面就会冻结,因为Dispatcher.Invoke经常更新文本框.
不知道是否有任何解决方法.我可以从文本文件中获取更大的块但不想破坏日志拖尾的实时体验,也不想延迟通过UI线程将行写入TextBox,因为这会使我的应用程序与实际数据不同步源文本文件.
这是后台工作者的DoWork方法
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
reader = new StreamReader(new FileStream(file.File, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
lastMaxOffset = reader.BaseStream.Length;
while (true)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
if (reader.BaseStream.Length == lastMaxOffset)
continue;
reader.BaseStream.Seek(lastMaxOffset, SeekOrigin.Begin);
string line = "";
while ((line = reader.ReadLine()) != null)
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, (Action)(() =>
{
textLog.Text += "\r" + line;
scrollViewer.ScrollToBottom();
}));
lastMaxOffset = reader.BaseStream.Position;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,UI线程只是简单地将文本附加到TextBox,并且当它经常发生接口冻结时
我明天早上必须提交我的WPF项目; 它在VS 2010中运行得很好,但是在使用C#的VS 2008(两种情况下都是.NET 3.5)中出错了.
我正在使用计时器,Dispatcher.Invoke但在VS 2008中它给出错误:
错误163
最佳重载方法匹配System.Windows.Threading.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority, System.Delegate)包含一些无效参数.
以下代码给出错误:
Dispatcher.Invoke(new Action(() =>
{
// ANY ACTIONS HERE
.. some task
}), null);
Run Code Online (Sandbox Code Playgroud)
代码必须在VS 2008中运行.
我收到了错误
'socketServer.Form1'不包含'Dispatcher'的定义,并且没有扩展方法'Dispatcher'接受类型为'socketServer.Form1'的第一个参数'
从
private void tbAux_SelectionChanged(object sender, EventArgs e)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
textBox.Text = tbAux.Text;
}
);
}
Run Code Online (Sandbox Code Playgroud)
根据文档,Dispatcher该类是System.Windows.Threading我正在使用的命名空间的一部分.
我错过了另一个参考吗?
如果它是相关的,我在使用服务器/客户端套接字收到"跨线程操作无效"的错误后添加了这个.
在wp8中对复杂任务进行排队的正确方法是什么?
任务包括以下内容:
ProgressIndicator通过更新模型变量UploadStringAsync)UploadStringCompleted.ProgressIndicator更新模型变量目前我一直在使用一个拥有命令对象队列的类,运行一个在添加项目时启动的线程(如果它尚未运行).
但是,我有等待代码停止运行的任务或子任务的问题.
以前我曾经使用异步等待,但是行为的几个级别变得越来越难以预测.
我想要的是能够创建和排队命令对象的主线程.命令对象应该一次运行一个,而不是在前一个完全完成之前启动一个新对象.如果需要,命令对象应该能够使用调度程序访问主线程.
我使用下面的代码来显示WPF(MVVM)应用程序中的进度条状态,该应用程序基本上是在一个线程上,但是如果我在调度程序线程上放置它的状态没有在UI上更新.
有线程:
Main()
{
Thread LoadApp = new Thread(MyData);
LoadApp.Start();
}
public void MyData()
{
ProgMessage = "10%";
ProgValue = 10;
var varAction = new List<Func<object>>();
varAction .Add(() => (MainViewMode1)ViewModel1.ViewModel1);
varAction .Add(() => (MainViewMode2)ViewModel2.ViewModel2);
varAction .Add(() => (MainViewMode3)ViewModel3.ViewModel3);
foreach (var action in varAction )
{
var obj = action();
ProgressMessage = // My message from VM
ProgressBarValue += // My message valuefrom VM;
}
Run Code Online (Sandbox Code Playgroud)
}
这工作正常但是从现在开始我使用依赖属性我得到了交叉线程异常(STA)所以我将代码更改为:
Main()
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
{
MyData();
}));
}
public void MyData()
{ …Run Code Online (Sandbox Code Playgroud) 我需要notifyService用Symphony的事件调度员替换我.
这是原始服务:
<?php
class VmService
{
/**
* @var VmManager|null
*/
protected $vmManager = null;
/**
* @var ProvisionerInterface[]
*/
protected $provisionners = array();
/**
* @var NotifyService|null
*/
protected $notifyService = null;
public function setVmManager(VmManager $vmManager)
{
$this->vmManager = $vmManager;
}
public function getVmManager()
{
return $this->vmManager;
}
/**
* @param $type
* @param ProvisionerInterface $provisionner
*/
public function setProvisionner($type, ProvisionerInterface $provisionner)
{
$this->provisionners[$type] = $provisionner;
}
/**
* @param $type
* @return ProvisionerInterface
*/
public function …Run Code Online (Sandbox Code Playgroud)