我获得了一个通用的API类,它包含一个自定义事件,它总是需要由主UI线程调用。 我的工作是从自定义类中消除这些调用调用,使其“无痛”#34;。
它应该像WinForms中的默认事件一样进行同步(例如Timer" Elapsed"事件,当它向文本框发布值时也不需要调用)
是否可以解决这个问题,因为自定义类需要知道调用的位置?
这里是代码的(重要部分):
public class ContactSensorHelper
{
public event OnReleaseStateChanged ReleaseStateChanged;
public delegate void OnReleaseStateChanged(ContactSensorEventArgs e);
private ContactSensorEventArgs.ReleaseState recentReleaseState;
public void ReportStateChanged()
{
if (ReleaseStateChanged != null)
ReleaseStateChanged(new ContactSensorEventArgs()
{
State = recentReleaseState
});
}
public class ContactSensorEventArgs : EventArgs
{
//......
public ReleaseState State { get; set; }
//......
public enum ReleaseState
{
FullReleased,
PartlyReleased,
NotReleased
}
}
}
来自主界面的电话:
public void SensorInit()
{
//....
sensorHelper.ReleaseStateChanged += releaseStateChanged;
//....
}
private void releaseStateChanged(ContactSensorEventArgs e)
{
//example
textBox1.Text = e.State.ToString(); // Thread exception (obviously)
}
有没有人让我开始提示?
答案 0 :(得分:1)
您可以通过使用自己的事件调用,并在附加事件时存储对线程的引用来执行此操作。
使用事件添加/删除语法,您可以让调用者像以前一样附加到事件,但在内部存储列表,并引用该线程(使用AsyncOperation)并且委托为调用(在示例中使用了包含两者的元组)
以下是一个例子。我对它进行了测试,并且在测试时它按预期工作,但是如果同时添加/删除事件,您可能必须添加一些列表锁定以使其线程安全。
public class ContactSensorHelper:IDisposable
{
public delegate void OnReleaseStateChanged(ContactSensorEventArgs e);
private ContactSensorEventArgs.ReleaseState recentReleaseState;
public void ReportStateChanged()
{
if (statechangedList.Count > 0)
{
var e = new ContactSensorEventArgs()
{
State = recentReleaseState
};
statechangedList.ForEach(t =>
t.Item1.Post(o => t.Item2((ContactSensorEventArgs)o), e));
}
}
List<Tuple<AsyncOperation, OnReleaseStateChanged>> statechangedList = new List<Tuple<AsyncOperation,OnReleaseStateChanged>>();
public event OnReleaseStateChanged ReleaseStateChanged
{
add
{
var op = AsyncOperationManager.CreateOperation(null);
statechangedList.Add(Tuple.Create(op, value));
}
remove
{
var toremove = statechangedList.Where(t => t.Item2 == value).ToArray();
foreach (var t in toremove)
{
t.Item1.OperationCompleted();
statechangedList.Remove(t);
}
}
}
public void Dispose()
{
statechangedList.ForEach(t => t.Item1.OperationCompleted());
statechangedList.Clear();
}
public class ContactSensorEventArgs : EventArgs
{
//......
public ReleaseState State { get; set; }
//......
public enum ReleaseState
{
FullReleased,
PartlyReleased,
NotReleased
}
}
}