-2

C# で単純な Windows フォーム アプリケーションを構築しようとしています。どこでlblIPAddressローカルIPアドレスをlblInfo表示し、IPアドレスの最終更新時刻を表示します。btnRefreshデータを更新するために使用されます。しかし、tickTimer_Elapsedイベントが発生するとすぐに、「クロススレッド操作が無効です: コントロール 'lblInfo' は、それが作成されたスレッド以外のスレッドからアクセスされました。」というエラーがスローされます。

提案してください。私の完全なコードを以下に示します。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using Time = System.Timers;
using Connect = System.Net.NetworkInformation.NetworkInterface;

namespace ShowMyIP
{
    public class UpdatedInfo
    {
        public string lastUpdate = string.Empty;
        public string localIP = string.Empty;
    }
    public partial class ShowLocalIP : Form
    {
        UpdatedInfo updatedIP;
        public static Time.Timer tickTimer = new Time.Timer();
        public const int INTERVAL = 60 * 1000;

        public ShowLocalIP()
        {
            InitializeComponent();
            InitializeTimer();

            updatedIP = new UpdatedInfo();
            updatedIP = GetLocalIP(updatedIP);
            lblIPAddress.Text = updatedIP.localIP;
            lblInfo.Text = updatedIP.lastUpdate;             
        }
        public void InitializeTimer()
        {
            tickTimer.Interval = INTERVAL;
            tickTimer.Enabled = true;
            tickTimer.Elapsed += new Time.ElapsedEventHandler(tickTimer_Elapsed);
            tickTimer.Start();
            GC.KeepAlive(tickTimer);
        }

        private void tickTimer_Elapsed(object sender, Time.ElapsedEventArgs e)
        {
            updatedIP = new UpdatedInfo();
            updatedIP = GetLocalIP(updatedIP);
            lblIPAddress.Text = updatedIP.localIP;
            lblInfo.Text = updatedIP.lastUpdate;           
            tickTimer.Interval = INTERVAL;
            tickTimer.Enabled = true;
            tickTimer.Start();
            GC.KeepAlive(tickTimer);
        }

        private UpdatedInfo GetLocalIP(UpdatedInfo UpdatedIP)
        {
            if (Connect.GetIsNetworkAvailable())
            {
                IPHostEntry host;
                host = Dns.GetHostEntry(Dns.GetHostName());

                foreach (IPAddress ip in host.AddressList)
                {
                    if (ip.AddressFamily == AddressFamily.InterNetwork)
                    {
                        UpdatedIP.localIP = ip.ToString();
                        UpdatedIP.lastUpdate = DateTime.Now.ToShortTimeString();
                        break;
                    }
                }
            }
            else
            {
                UpdatedIP.localIP = "127.0.0.1";
                UpdatedIP.lastUpdate = DateTime.Now.ToShortTimeString();                
            }
            return UpdatedIP;
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            updatedIP = new UpdatedInfo();
            updatedIP = GetLocalIP(updatedIP);
            lblIPAddress.Text = updatedIP.localIP;
            lblInfo.Text = updatedIP.lastUpdate;             
        }
    }
}
4

2 に答える 2

3

System.Timers.Timer の代わりに System.Windows.Forms.Timer を使用しないのはなぜですか? System.Windows.Forms.Timer は、このクラスの問題を回避するように設計されています。

于 2013-08-14T16:15:47.070 に答える
1

タイマー スレッドから UI で操作を「呼び出す」必要があります。Invoke 呼び出しなしでは、Winforms UI でのクロススレッド呼び出しは許可されません。

別のスレッドから UI メソッドを呼び出す方法

于 2013-08-14T16:16:47.803 に答える