簡體   English   中英

訪問不同線程中的對象

[英]Access object in a different thread

設定:

Win10 .NET 4.7.1 / VS2017 .NET 4.5 / C#

水平:

初學者/中級/線程新手

目的:

1:由計時器類觸發的Selenium Web自動化類,以便Web自動化類可以在特定時間與javascript站點交換數據。

2:應該可以將解決方案從WebForms遷移到.NET庫(dll)。

問題:

步驟1.計時器類將時間事件發送到Web類中的方法以登錄Internet站點=工作。

步驟2. Web自動化類(WinForms / GUI)嘗試從計時器類event = event觸發的方法中檢索數據:異常:“調用線程無法訪問該對象,因為另一個線程擁有它。” (從swe翻譯而來)。

我承認我對新的線程領域的術語感到困惑。 另外,我了解一些多線程技術僅對WinForms有效。 由於我的目標是將解決方案遷移到dll,因此這些都不是我的選擇。 我玩過Invoke(),但是據我所知,它只能在WinForms中使用。 指導受到高度贊賞!

網絡自動化課程:

    private EdgeDriver driver;
    private SeleniumHelper helper;
    private WebAutomationTimer timer;
    private double account;

    public double Account { get => this.account; set => this.account = value; }

    public Form1()
    {
        InitializeComponent();
        timer = new WebAutomationTimer(02, 36, 00, 02, 38, 00);
        timer.OnLoginTime += Timer_OnLoginTime;
        timer.OnLogoutTime += Timer_OnLogoutTime;
    }

    private void Timer_OnLoginTime()
    {
        Login();
    }

    private void Timer_OnLogoutTime()
    {
        Logout();
    }

    public bool Login()
    {
        try
        {
            // working login code

    UpdateLabels();
        }
        catch (Exception e)
        {

        }
    }

    private void UpdateLabels()
    {
        // EXCEPTION !!!
        lblAccount.Text = GetAccount(); 
    // EXCEPTION !!!
    }

計時器類:

class WebAutomationTimer
{
    public event TimerEvent OnLoginTime;
    public event TimerEvent OnLogoutTime;
    //public event TimerEvent OnSecond;
    private System.Timers.Timer timer;
    private DateTime now;
    private int loginHour;
    private int loginMin;
    private int loginSec;
    private int logoutHour;
    private int logoutMin;
    private int logoutSec;

    public WebAutomationTimer(int loginHour, int loginMin, int loginSec, int logoutHour, int logoutMin, int logoutSec)
    {
        timer = new System.Timers.Timer();
        timer.Interval = 1000; // 1 sec
        timer.Elapsed += Timer_Elapsed;
        timer.Start();
        this.loginHour = loginHour;
        this.loginMin = loginMin;
        this.loginSec = loginSec;
        this.logoutHour = logoutHour;
        this.logoutMin = logoutMin;
        this.logoutSec = logoutSec;
    }

    // Each second event
    private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        now = DateTime.Now;
        //OnSecond();

        //login
        if (now.Hour == loginHour && now.Minute == loginMin && now.Second == loginSec)
            OnLoginTime();

        //logout
        if (now.Hour == logoutHour && now.Minute == logoutMin && now.Second == logoutSec)
            OnLogoutTime();
    }
}

}

當您想從另一個Thread更新View的控件時,它必須顯示錯誤。 因為它是通過UI Thread使用的。 在這種情況下,您必須使用SynchronizationContext類,或者可以將Delegate發送到App.Current.Dispatcher.BeginInvoke(delegate must be here)

SynchronizationContext _context = SynchronizationContext.Current;

private void UpdateLabels()
{
        _context.Post(x=> 
             {
                lblAccount.Text = AccountBalance.ToString();
             },null),

    //...
}

SynchronizationContext的替代方法:

private void UpdateLabels()
{
      var action = new Action(() => 
      {
              lblAccount.Text = AccountBalance.ToString();
      });

      App.Current.Dispatcher.BeginInvoke(action);

    //...
}

他們都是一樣的。

適用於鍵盤事件和鼠標事件的UI線程。 當您App.Current.Dispatcher.BeginInvoke(delegate)您對“也執行此操作”的UI Thread說。

另外,您可以假設這樣的UI Thread

while(!thisApplication.Ended)
{
    wait for something to appear  in message queue
    Got something : what kind of this message? 
    Keyboard/Mouse message --> fire event handler 
    User BeginInvoke message --> execute delegate
    User Invoke message --> execute delegate & post result

}

此錯誤是因為更改標簽文字,因為標簽在另一個線程中,您可以使用此代碼

 lblAccount.Invoke(new EventHandler((s, ee) => { lblAccount.Text = AccountBalance.ToString(); }));

該解決方案可能僅對我而言有效。 如果認為重復,OP可以刪除該問題。

第一個目標是使用GUI輕松開發/運行/調試情況。 設置屬性不會導致跨線程異常。 在MessageBox.Show()中顯示屬性也不會引起異常。 因此,在開發/ GUI階段無需交叉線程問題。

第二個目標是遷移到dll,因此無需干擾GUI線程。

/不管怎么說,還是要謝謝你

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM