线程问题中的计时器

时间:2011-06-01 23:54:45

标签: c# multithreading datagridview timer

我有我的应用程序,其中三个datagridview独立于wcf服务的三个线程加载数据。我在每个线程计时器中执行,每秒加载一次这个数据。

我的问题是每次我的线程都抛出每个线程,但只是像我在方法timerNowyYork_Elapsed中显示的那样

知道为什么会这样吗?我的锁线程不好?

此代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace Sprawdzanie_warunków_pogodowych
{
public partial class Form1 : Form
{
    PogodaEntities entity = new PogodaEntities();
    System.Timers.Timer timerKrakow = new System.Timers.Timer();
    System.Timers.Timer timerSzczecin = new System.Timers.Timer();
    System.Timers.Timer timerNowyYork = new System.Timers.Timer();
    KeyValuePair<string, string> krakowInfo;
    KeyValuePair<string, string> szczecinInfo;
    KeyValuePair<string, string> nowyYorkInfo;

    public Form1()
    {
        System.Net.ServicePointManager.Expect100Continue = false;
        InitializeComponent();
        List<MiastoContainer> miasta = (from miasto in entity.Miasta
                                        select new MiastoContainer()
                                   {
                                       MiastoName = miasto.Nazwa,
                                       Panstwo = miasto.Państwo
                                   }).ToList();
        krakowInfo = new KeyValuePair<string, string>(miasta[0].MiastoName, miasta[0].Panstwo);
        szczecinInfo = new KeyValuePair<string, string>(miasta[1].MiastoName, miasta[1].Panstwo);
        nowyYorkInfo = new KeyValuePair<string, string>(miasta[2].MiastoName, miasta[2].Panstwo);

        ParameterizedThreadStart ptsKrakow = new ParameterizedThreadStart(PobierzKrakow);
        Thread tKrakow = new Thread(ptsKrakow);
        tKrakow.Start(this.dataGridViewKrakow);

        ParameterizedThreadStart ptsSzczecin = new ParameterizedThreadStart(PobierzSzczecin);
        Thread tSzczecin = new Thread(ptsSzczecin);
        tSzczecin.Start(this.dataGridViewSzczecin);
    }

    private void oAutorzeToolStripMenuItem_Click(object sender, EventArgs e)
    {
        new AboutBox1().Show();
    }

    private void zapiszRaportToolStripMenuItem_Click(object sender, EventArgs e)
    {

    }

    public void PobierzKrakow(object parameters)
    {
        this.timerKrakow.Elapsed += new System.Timers.ElapsedEventHandler(timerKrakow_Elapsed);
        this.timerKrakow.Enabled = true;
        this.timerKrakow.Interval = 1000;
        this.timerKrakow.Start();
    }

    public void PobierzSzczecin(object parameters)
    {
        this.timerSzczecin.Elapsed += new System.Timers.ElapsedEventHandler(timerSzczecin_Elapsed);
        this.timerSzczecin.Enabled = true;
        this.timerSzczecin.Interval = 1000;
        this.timerSzczecin.Start();
    }

    public void PobierzNowyYork(object parameters)
    {
        this.timerNowyYork.Elapsed += new System.Timers.ElapsedEventHandler(timerNowyYork_Elapsed);
        this.timerNowyYork.Enabled = true;
        this.timerNowyYork.Interval = 1000;
        this.timerNowyYork.Start();
    }

    void timerNowyYork_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {  GlobalWeather.Weather weather = new GlobalWeather.Weather();
        lock (weather)
        {
            //thread always start from here
            List<object> weatherList = new List<object>();
            weatherList.Add(weather.GetTempreature(nowyYorkInfo.Key, nowyYorkInfo.Value));
           //and end here , never come any line further
            weatherList.Add(weather.GetPressure(nowyYorkInfo.Key, nowyYorkInfo.Value));
            weatherList.Add(weather.GetHumidity(nowyYorkInfo.Key, nowyYorkInfo.Value));
            weatherList.Add(weather.GetVisibility(nowyYorkInfo.Key, nowyYorkInfo.Value));
            entity.SaveChanges();

            WarunkiPogodowe warunki = new WarunkiPogodowe()
            {
                Temperatura = weatherList[0].ToString(),
                Ciśnienie = weatherList[1].ToString(),
                Wilgotność = weatherList[2].ToString(),
                Widoczność = weatherList[3].ToString(),
                DataSprawdzenia = DateTime.Now
            };
            entity.AddToWarunkiPogodowe(warunki);
            entity.SaveChanges();
            int miastoId = entity.Miasta.First(m => m.Nazwa == nowyYorkInfo.Key).id;
            Miasto_has_WarunkiPogodowe m_has_wp = new Miasto_has_WarunkiPogodowe()
            {
                idMiasto_FK = miastoId,
                idWarunkiPogodowe_FK = warunki.id
            };
            entity.AddToMiasto_has_WarunkiPogodowe(m_has_wp);
            entity.SaveChanges();

            this.dataGridViewNowyYork.Rows.Add(warunki);
        }
    }

    void timerSzczecin_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        GlobalWeather.Weather weather = new GlobalWeather.Weather();

        lock (weather)
        {
            List<object> weatherList = new List<object>();
            weatherList.Add(weather.GetTempreature(szczecinInfo.Key, szczecinInfo.Value));
            weatherList.Add(weather.GetPressure(szczecinInfo.Key, szczecinInfo.Value));
            weatherList.Add(weather.GetHumidity(szczecinInfo.Key, szczecinInfo.Value));
            weatherList.Add(weather.GetVisibility(szczecinInfo.Key, szczecinInfo.Value));
            entity.SaveChanges();

            WarunkiPogodowe warunki = new WarunkiPogodowe()
            {
                Temperatura = weatherList[0].ToString(),
                Ciśnienie = weatherList[1].ToString(),
                Wilgotność = weatherList[2].ToString(),
                Widoczność = weatherList[3].ToString(),
                DataSprawdzenia = DateTime.Now
            };
            entity.AddToWarunkiPogodowe(warunki);
            entity.SaveChanges();
            int miastoId = entity.Miasta.First(m => m.Nazwa == szczecinInfo.Key).id;
            Miasto_has_WarunkiPogodowe m_has_wp = new Miasto_has_WarunkiPogodowe()
            {
                idMiasto_FK = miastoId,
                idWarunkiPogodowe_FK = warunki.id
            };
            entity.AddToMiasto_has_WarunkiPogodowe(m_has_wp);
            entity.SaveChanges();

            this.dataGridViewSzczecin.Rows.Add(warunki);
        }
    }
    void timerKrakow_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        GlobalWeather.Weather weather = new GlobalWeather.Weather();

        lock (weather)
        {
            List<object> weatherList = new List<object>();
            weatherList.Add(weather.GetTempreature(krakowInfo.Key, krakowInfo.Value));
            weatherList.Add(weather.GetPressure(krakowInfo.Key, krakowInfo.Value));
            weatherList.Add(weather.GetHumidity(krakowInfo.Key, krakowInfo.Value));
            weatherList.Add(weather.GetVisibility(krakowInfo.Key, krakowInfo.Value));
            entity.SaveChanges();

            WarunkiPogodowe warunki = new WarunkiPogodowe()
            {
                Temperatura = weatherList[0].ToString(),
                Ciśnienie = weatherList[1].ToString(),
                Wilgotność = weatherList[2].ToString(),
                Widoczność = weatherList[3].ToString(),
                DataSprawdzenia = DateTime.Now
            };
            entity.AddToWarunkiPogodowe(warunki);
            entity.SaveChanges();
            int miastoId = entity.Miasta.First(m => m.Nazwa == krakowInfo.Key).id;
            Miasto_has_WarunkiPogodowe m_has_wp = new Miasto_has_WarunkiPogodowe()
            {
                idMiasto_FK = miastoId,
                idWarunkiPogodowe_FK = warunki.id
            };
            entity.AddToMiasto_has_WarunkiPogodowe(m_has_wp);
            entity.SaveChanges();

            this.dataGridViewKrakow.Rows.Add(warunki);
        }
    }
}

class MiastoContainer
{
    string miastoName;

    public string MiastoName
    {
        get { return miastoName; }
        set { miastoName = value; }
    }
    string panstwo;

    public string Panstwo
    {
        get { return panstwo; }
        set { panstwo = value; }
    }

    public MiastoContainer()
    { }

    public MiastoContainer(string miasto, string panstwo)
    {
        this.MiastoName = miasto;
        this.Panstwo = panstwo;
    }

    public void Add(MiastoContainer item)
    {
        ((ICollection<MiastoContainer>)this).Add(item);
    }

}

}

4 个答案:

答案 0 :(得分:2)

你的锁完全没用。当您锁定刚刚创建的对象时,每个锁都将拥有自己的标识符,并且根本不会相互影响。

您需要所有应相互排斥的锁以使用与标识符相同的对象。

答案 1 :(得分:2)

System.Timers.Timer允许您设置SynchronizingObject,以便它将调用UI线程上的回调。创建计时器时,请写下:

this.timerKrakow.SynchronizingObject = this;

然后将在UI线程上调用计时器的已用事件。这消除了事件处理程序中锁定的需要。

顺便说一下,你可以用System.Windows.Forms.Timer做同样的事情,它始终在UI线程上调用事件处理程序。

在UI线程上引发事件的缺点是它可能会阻止用户界面。这取决于事件处理程序花费了多少时间。如果您的事件处理程序非常快,那么这不是问题。但是,如果处理事件处理程序需要100毫秒,您可能不希望在UI线程上执行此操作。

如果您选择不在UI线程上执行此操作,则需要同步对UI的访问。 timer事件处理程序不能只修改用户界面元素。相反,您需要调用this.Invoke,以便在UI线程上完成任何UI修改。

我强烈建议您不要使用System.Timers.Timer。正如documentation所述:

  

定时器组件捕获和   抑制所引发的所有异常   Elapsed事件的事件处理程序。   此行为可能会发生变化   .NET Framework的未来版本。

换句话说,如果您的事件处理程序中存在抛出异常的错误,您将永远不会知道它。我建议改用System.Windows.Forms.TimerSystem.Threading.Timer

答案 2 :(得分:0)

我不完全理解你的问题,但是(除非我弄错了)计时器回调发生在ThreadPool(或GUI线程,取决于用法),所以在不同的线程中启动它们是没有意义的。

答案 3 :(得分:0)

在我看来,您正在从另一个线程直接访问DataGridView。你不应该这样做。必须始终从UI线程调用UI控件。您可以使用ISynchronizeInvoke接口将数据传递到正确的线程中。

this.dataGridViewNowyYork.Invoke(new Action(() => {
    this.dataGridViewNowyYork.Rows.Add(warunki);
}), null);