我是使用Windows窗体应用程序开发的新手,我有一个问题,我可以就我应该采取的最佳实践方法提供一些帮助/指导。
背景:
我有一个基于表单的应用程序,需要使用来自WCF服务的数据每分钟刷新一次,然后使用列表视图控件中的最新结果更新UI。我这一切都在原则上工作,但应用程序间歇性崩溃,我需要解决这个问题。我已经删除了下面代码的主要部分。可能不需要实际的螺母和螺栓。
代码:
public partial class Form1 : Form
{
readonly MatchServiceReference.MatchServiceClient _client = new MatchServiceReference.MatchServiceClient();
public Form1()
{
_client.GetMMDataCompleted += new EventHandler<GetMMDataCompletedEventArgs>(_client_GetMMDataCompleted);
}
//Arm Timer
private void ArmTimer(object sender, EventArgs e)
{
aTimer = new Timer();
aTimer.Elapsed += OnTimedEvent;
aTimer.Interval = 60000;
aTimer.Enabled = true;
}
//Timer elapsed event
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
try
{
LoadMatches();
if (LastUpdated.InvokeRequired)
{
LastUpdated.Invoke(new MethodInvoker(delegate { LastUpdated.Text = e.SignalTime.ToString(); }));
}
}
catch (Exception exception)
{
}
}
//Load matches
private void LoadMatches()
{
try
{
aTimer.Enabled = false;
_client.GetMMDataAsync();
}
catch (Exception e)
{
//EventLog.WriteEntry("Application", e.InnerException.ToString(), EventLogEntryType.Error);
aTimer.Enabled = true;
}
}
void _client_GetMMDataCompleted(object sender, GetMMDataCompletedEventArgs e)
{
if (e.Result != null)
{
var matches = e.Result;
Debug.WriteLine("Matches received from service");
if (!IsHandleCreated && !IsDisposed) return;
// Invoke an anonymous method on the thread of the form.
Invoke((MethodInvoker) delegate
{
try
{
LoadTheMonitorMatches(matches);
}
catch (Exception exception)
{
Debug.WriteLine("INNER EXCEPTION" + exception.InnerException);
Debug.WriteLine("EXCEPTION MESSAGE" + exception.Message);
}
});
}
aTimer.Enabled = true;
}
}
}
例外:
我得到的例外情况如下 -
异常信息:System.Reflection.TargetInvocationException 堆: 在System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary() 在MM.MatchServiceReference.GetMMDataCompletedEventArgs.get_Result() 在MM.Form1._client_GetMMDataCompleted(System.Object,MM.MatchServiceReference.GetMMDataCompletedEventArgs) at MM.MatchServiceReference.MatchServiceClient.OnGetMMDataCompleted(System.Object) 在System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object) 在System.Threading.ExecutionContext.runTryCode(System.Object) 在System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode,CleanupCode,System.Object) 在System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object) 在System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object,Boolean) 在System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在System.Threading.ThreadPoolWorkQueue.Dispatch() 在System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
对此有任何帮助/建议将不胜感激。
干杯
答案 0 :(得分:2)
你使用了错误的计时器。 System.Timers.Timer
旨在用于服务器。对于Winform应用程序,您应该使用System.Windows.Forms.Timer
并将其作为控件添加到表单中。当您使用它时,UI会在计时器滴答之间做出响应,但是当它带来数据时,UI将变得无法响应。如果它不够好,您应该使用BackgroundWorker
。
如果在使用这些组件后问题仍然存在,请再次提出问题。
答案 1 :(得分:1)
该行
if (e.Result != null)
实际上是调用getter获取结果。由于事件args派生自AsyncCompletedEventArgs,因此如果操作被取消或出错,则会引发错误。在测试结果之前先检查已取消和错误属性,您应该能够捕获问题。
来自文档:
If the component's asynchronous worker code assigns an exception to the Error property or sets the Cancelled property to true, the property will raise an exception if a client tries to read its value.