我是线程新手;事实上,我甚至没有尝试多线程处理我正在处理的Windows窗体应用程序,但是我在这个问题上的所有搜索引导我进入多线程主题。在Visual Studio 2010 Express中进行调试时,似乎“跳转”使用我见过其他人用来描述相同问题的术语。当我让它运行时,有时会按预期运行,有时它似乎继续运行,挂起。
在试图磨练我的问题时,我想我需要弄清楚:
如果计时器类在不同的线程上调用方法,并且执行代码中没有明显的不可预测的实例值/状态损坏的危险(没有实例变量的任何条件检查等) ,为什么定时器调用的方法似乎行为不可预测?对我来说,似乎代码应该同步运行,如果一个不同的线程用于进程的一部分,那就这样吧。我看不出哪里有线程损坏的机会。
程序启动时,会提示设置计时器以运行数据下载过程。过程运行后,计时器再次设置为过程结束时的默认时间。始终如一,初始计时器设置工作,并按预期启动,运行数据下载过程...这是数据下载方法,在其中的某个地方出错。最后一行代码是再次设置计时器,但我无法判断它是否在调试时被点击。 (跳来跳去)..
我在下面添加了相关代码......我从一开始就进入了我的代码中的每个程序......它们都显示当前的线程ID 10.这取决于包括计时器启动,并在在下一行执行的断点,即数据下载过程。那时的当前线程:14。我在运行它/尝试调试btw之前构建了解决方案。有什么想法吗?
public partial class frmTradingAppMain : Form
{
private TradingAppDataRunManager drm;
private void frmTradingAppMain_Shown(object sender, EventArgs e)
{
drm = new TradingAppDataRunManager();
drm.StatusChanged += new DataRunManager.DRMStatusChangeHandler(UpdateFormData);
drm.InitializeOrScheduleDataRun();
}
private void UpdateFormData()
{
this.Invoke(new DataRunManager.DRMStatusChangeHandler(UpdateFormDataImpl));
}
private void UpdateFormDataImpl()
{
lblDataDwnLoadManagerStatus.Text = Convert.ToString(drm.Status);
if (drm.Status == DataRunManager.DRMStatus.Inactive)
{
lblNextScheduledDataDownloadDate.Text = "Date not set.";
lblNextScheduledDataDownloadTime.Text = "Time not set.";
}
else
{
lblNextScheduledDataDownloadDate.Text = drm.DateTimeOfNextScheduledDataRun.ToShortDateString();
lblNextScheduledDataDownloadTime.Text = drm.DateTimeOfNextScheduledDataRun.ToShortTimeString();
}
}
}
public abstract class DataRunManager
{
protected DataRunTimer dataRuntimer;
public delegate void DRMStatusChangeHandler();
public event DRMStatusChangeHandler StatusChanged;
public DRMStatusChangeHandler statusChanged;
public void InitializeOrScheduleDataRun()
{
if (DataRunIsAvailable() && UserWouldLikeToPerformDataRun())
RunMainDataProcedure(null);
else
ScheduleDataRun();
}
public void RunMainDataProcedure(object state)
{
start = DateTime.Now;
Status = DRMStatus.Running;
StatusChanged();
GetDataCollections();
foreach (DataCollection dcl in dataCollectionList)
{
dcl.RunDataCollection();
dcl.WriteCollectionToDatabase();
}
PerformDBServerSideProcs();
stop = DateTime.Now;
WriteDataRunStartStopTimesToDB(start, stop);
SetDataRunTimer(DateTimeOfNextAvailableDR());
}
public void ScheduleDataRun()
{
FrmSetTimer frmSetTimer = new FrmSetTimer(DateTimeOfNextAvailableDataRun);
DateTime currentScheduledTimeOfNextDataRun = DateTimeOfNextScheduledDataRun;
DRMStatus currentStatus= Status;
try
{
frmSetTimer.ShowDialog();
DateTimeOfNextScheduledDataRun = (DateTime)frmSetTimer.Tag;
SetDataRunTimer(DateTimeOfNextScheduledDataRun);
}
catch
{
Status = currentStatus;
DateTimeOfNextScheduledDataRun = currentScheduledTimeOfNextDataRun;
}
}
}
public class DataRunTimer
{
System.Threading.Timer timer;
public DataRunTimer(){}
public void SetNextDataRunTime(TimerCallback timerCallback, DateTime timeToSet)
{
if (timer == null)
timer = new System.Threading.Timer(timerCallback);
TimeSpan delayTime = new TimeSpan(timeToSet.Day - DateTime.Now.Day, timeToSet.Hour - DateTime.Now.Hour, timeToSet.Minute - DateTime.Now.Minute,
timeToSet.Second - DateTime.Now.Second);
TimeSpan intervalTime = new TimeSpan(0, 0, 10);
timer.Change(delayTime, intervalTime);
}
public void DataRunTimerCancel()
{
if (timer != null)
timer.Dispose();
}
}