在我的应用程序中,我有一个与PLC通信的通讯驱动程序,这很好用。我想管理所有的值更新请求,为此我创建了在ValueListenManager中注册自己的ValueListener对象,这也可以正常工作。在我的同步测试中,UI性能如预期的那样缓慢。现在完美让我们让它变得异步。
我尝试了不同的方法,例如backgroundworker,timer和Task.Run 这是迄今为止我能做的最好的,它可以正常工作,如果我printcreen任务ManagedThreadId线程ID是不同的(什么告诉我它应该是异步的)
但UI响应性能似乎并没有真正改善,这告诉我它并不是真正的异步。谁能帮我这个?
到目前为止,我发现的唯一奇怪的事情是,当CheckPlcValuesTask已经更新时,可以将ValueListener添加到Managers ListenList,这也表明我不是真的异步,我做错了什么? (我是异步编程的新手,所以感谢任何帮助或提示)
编辑:代码现在编译
public class CommManager
{
public static class ValueListenManager
{
static private List<ValueListener> ListenList = new List<ValueListener>();
public async static void Start()
{
var UpdateChangedValues = new Progress<List<ValueListener>>(UiUpdateList =>
{
foreach (ValueListener item in UiUpdateList)
item.TriggerChange();
});
await Task.Run(() => CheckPlcValuesTask(UpdateChangedValues));
}
private static Task CheckPlcValuesTask(IProgress<List<ValueListener>> progressList)
{
List<ValueListener> returnList = new List<ValueListener>();
while (true)
{
if (returnList.Count != 0)
returnList.Clear();
Parallel.ForEach(ListenList, (CurrentItem) => // ListenList is the static List declared in the top
{
if (CurrentItem.CheckValue())
returnList.Add(CurrentItem);
});
if (progressList != null)
{
progressList.Report(returnList);
Thread.Sleep(1000);
}
}
}
static internal void RegisterLister(ValueListener Listner)
{
ListenList.Add(Listner);
}
static internal void UnRegisterLister(ValueListener Listner)
{
ListenList.Remove(Listner);
}
}
}
}
internal class ValueListener
{
public event EventHandler<ValueChangeEventArgs> Changed;
public string FullPath { get; }
public object Value { get; private set; }
private object oldObjectValue;
internal ValueListener(string Path) // update prio is a enum
{
this.FullPath = Path;
CommManager.ValueListenManager.RegisterLister(this); // here i register into the ListenList above
}
~ValueListener()
{
CommManager.ValueListenManager.UnRegisterLister(this); // de-register after destruction
}
// Check for value changes
public bool CheckValue()
{
var SmallTest = new Random();
Value = SmallTest.Next(1, 5);
if (Value != null && !Value.Equals(oldObjectValue))
return true;
return false;
}
// Check for value change, here is where i trigger updates on the UI
public void TriggerChange()
{
if (Changed != null)
Changed.Invoke(this, new ValueChangeEventArgs(Value, oldObjectValue));
oldObjectValue = Value;
}
}
public class ValueChangeEventArgs : EventArgs
{
public ValueChangeEventArgs(object Value, object OldValue)
{ }
}
答案 0 :(得分:0)
这应该对你有用。它利用了Microsoft TPL Dataflow, 这是一个nuget包。
public static partial class CommManager
{
public static class ValueListenManager
{
public static event Action<object> NewValueAvailable;
private static Thread s_valueQueryThread;
private static ActionBlock<object> s_newValueActionBlock;
private static bool s_shouldRun;
private static Random s_valueGenerator; //for testing purposes
public static void Start()
{
//These flow options will make sure your action block executes on the UI thread. Make sure you call start on the UI Thread!
var flowOptions = new ExecutionDataflowBlockOptions(){ TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext() };
s_newValueActionBlock = new ActionBlock<object>(new Action<object>(OnNewValue), flowOptions);
s_valueQueryThread = new Thread(CheckPlcValues);
s_valueQueryThread.IsBackground = true;
s_valueQueryThread.Start();
}
public static void Stop()
{
s_shouldRun = false;
s_valueQueryThread.Join();
s_valueQueryThread = null;
s_newValueActionBlock.Complete();
s_newValueActionBlock = null;
}
private static void OnNewValue(object value)
{
if(NewValueAvailable != null)
NewValueAvailable(value);
}
private static void CheckPlcValues()
{
s_shouldRun = true;
while(s_shouldRun)
{
var curPlcValue = s_valueGenerator.Next(1, 5);
s_newValueActionBlock.Post(curPlcValue);
Thread.Sleep(1000);
}
}
}
}
internal class ValueListener
{
public event EventHandler<ValueChangeEventArgs> ValueChanged;
public string FullPath { get; private set; }
public object Value { get; private set; }
internal ValueListener(string path)
{
this.FullPath = path;
CommManager.ValueListenManager.NewValueAvailable += CommManager_ValueListenManager_NewValueAvailable;
}
~ValueListener()
{
CommManager.ValueListenManager.NewValueAvailable -= CommManager_ValueListenManager_NewValueAvailable;
}
void CommManager_ValueListenManager_NewValueAvailable(object newValue)
{
if(newValue != null && !newValue.Equals(Value))
{
var args = new ValueChangeEventArgs(newValue, Value);
Value = newValue;
if(ValueChanged != null)
ValueChanged(this, args);
}
}
}
public class ValueChangeEventArgs : EventArgs
{
public ValueChangeEventArgs(object Value, object OldValue) { }
}