Я новичок в потоках; на самом деле я даже не пытаюсь создать многопоточное приложение Windows Forms, над которым я работаю, но все мои поиски по этой проблеме привели меня к теме многопоточности. При отладке в Visual Studio 2010 Express кажется, что он «перепрыгивает», используя термин, который, как я видел, используют другие, для описания той же проблемы. Когда я позволяю ему работать, иногда он работает, как ожидалось, в других случаях кажется, что он продолжает работать, зависает.
Пытаясь отточить мой вопрос, я думаю, мне нужно выяснить:
Если класс timer вызывает метод в другом потоке, и в исполняемом коде нет явной опасности непредсказуемых значений экземпляров / повреждения состояния (нет никаких условных проверок переменных экземпляра и т. Д.) Почему этот метод, вызываемый таймером, ведет себя непредсказуемо? Мне кажется, что код должен выполняться синхронно, и если для части процесса используется другой поток, пусть будет так. Я не вижу, где есть возможность порчи потока.
Когда программа запускается, она предлагает установить таймер для запуска процесса загрузки данных. После запуска процедуры таймер снова устанавливается на время по умолчанию в конце процедуры. Соответственно, первоначальная настройка таймера работает и срабатывает, как и ожидалось, при запуске процесса загрузки данных ... это тот метод загрузки данных, где-то в нем происходит сбой. Последняя строка кода - это то, что снова устанавливает таймер, но я не могу сказать, ударил ли он при отладке. (прыгает вокруг) ..
Я добавил соответствующий код ниже ... и я приступил к каждой процедуре в моем коде с самого начала ... все они показывают текущий идентификатор потока 10. Это включает в себя включение таймера и остановку на точка останова на следующей строке для выполнения, которая является процессом загрузки данных. Текущий поток на тот момент: 14. Я построил решение перед его запуском / попыткой отладки между прочим. Есть идеи?
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();
}
}