2

我有一种Async方法可以关闭一些浏览器弹出窗口。

有时,应用程序在退出时崩溃并出现.NET Runtime错误(mscorwks.dll异常代码为0xc0000005)。我怀疑它Thread是在被迫终止时发生的,因为我看不到记录的“线程退出”行。会不会是里面的代码ExtendedIeBrowser抛出一个unhandled exception?

您可以在下面找到源代码。

internal void KeepAliveAsync()
{
    PageController controller = new PageController();
    controller.Initialize(siteWebBrowser);

    var thread = new Thread(() =>
    {
        _logger.Debug("Thread start - KeepAliveAsync");
        try
        {
            while (!Program.ShouldAbortBackgroundOperations())
            {
                try
                {
                    if (controller.TryCloseTimeoutWarningPopup())
                    {
                        _logger.Info("KeepAliveAsync: Closed popup successfully");
                    }

                    Thread.Sleep(5000);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("KeepAliveAsync", ex);
                }
            }
        }
        catch (Exception ex)
        {
            _logger.ErrorException("KeepAliveAsync", ex);
        }
        _logger.Debug("Thread exit - KeepAliveAsync");
    });
    thread.Name = "KeepAliveAsync";
    thread.IsBackground = true;
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
}

使用PageController这个类:

public class ExtendedIeBrowser : IE
{
    private IntPtr hwnd;
    private static Logger _logger = LogManager.GetCurrentClassLogger();

    public ExtendedIeBrowser(WebBrowser webBrowserControl) : base(webBrowserControl.ActiveXInstance, false)
    {
    }

    public void Initialize(WebBrowser webBrowserControl)
    {
        hwnd = webBrowserControl.FindForm().Handle;

        // Start the dialog watcher or else the browser won't be able to attach the handler.
        StartDialogWatcher();
    }
    public override IntPtr hWnd
    {
        get
        {
            return hwnd;
        }
    }

    protected override void Dispose(bool disposing)
    {
        hwnd = IntPtr.Zero;
        base.Dispose(disposing);
    }
}

这是:

    internal static bool ShouldAbortBackgroundOperations()
    {
        bool should = true;

        try
        {
            should &= Application.OpenForms.Cast<Form>().Count(f => f.ShowInTaskbar) == 0; // at least one form is shown in the taskbar
        }
        catch (Exception ex)
        {
            _logger.ErrorException("ShouldAbortBackgroundOperations", ex);
            should = false;
        }

        return should;
    }

关闭弹出窗口的方法(字面意思是网页内的 div):

    internal bool TryCloseTimeoutWarningPopup()
    {
        bool success = false;
        try
        {
            Div glassPane = Browser.Div(Find.ByClass(PageConstants.ModalGlassPaneClass));
            if (glassPane.Exists) // there is a popup
            {
                Div parent = (Div)glassPane.Parent;
                if (parent.InnerHtml.Contains(PageConstants.WarningLoggingOutPrimaryKeyword)) // correct content on popup
                {
                    WatiN.Core.Button button = parent.Divs[0].Buttons[0];
                    ClickOnElement(button);
                    success = true;
                }
            }
        }
        catch (Exception ex)
        {
            _logger.ErrorException("CloseTimeoutWarningPopup", ex);
            throw;
        }
        return success;
    }

如果程序在 Abort 检查和 CloseTimeoutWarningPopup() 执行后关闭怎么办?我注意到在我关闭应用程序后的某个时间点,该if (glassPane)行正在等待元素出现并尝试访问已处置的对象。是否该对象的内存地址不再可用并因此被拒绝?

4

1 回答 1

1

问题是一些controller试图访问的控件在线程终止之前被释放,导致访问冲突异常

于 2012-12-22T12:58:06.600 回答