如何确保在应用程序关闭之前以单例方式处理对象? [英] How can I ensure that I dispose of an object in my singleton before the application closes?

查看:79
本文介绍了如何确保在应用程序关闭之前以单例方式处理对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用WatiN进行一些自动化测试,结果发现,为每个测试创建IE实例都是不可扩展的。每个IE实例的创建和关闭时间都在吞噬着我:

I'm using WatiN for some automated tests and what I found was that creating an IE instance for every test was not scalable. The creation and shutdown time of each IE instance was eating me alive:

    [TestMethod]
    public void Verify_Some_Useful_Thing()
    {
        using (var browser = new IE())
        {
            browser.GoTo("/someurl");
            // etc..
            // some assert() statements
        }
     }

但是,using语句确实有用,因为我可以始终确保IE实例具有其dispose()方法,该方法将关闭IE窗口。

However, the using statement did prove useful in that I can always ensure that my IE instance would have its dispose() method called which would close the IE window.

无论如何,我创建了一个单例,该单例维护一个IE实例,我的所有测试均在所有测试类中使用该IE实例:

Anyway, I created a singleton which maintained a single IE instance which all my tests use across all my test classes:

public class BrowserPool
{      
    private static readonly Lazy<BrowserPool> _instance = new Lazy<BrowserPool>(() => new BrowserPool());        

    private IE _browser;
    private string _ieHwnd;
    private int _threadId;

    public IE Browser
    {
        get
        {
            var currentThreadId = GetCurrentThreadId();
            if (currentThreadId != _threadId)
            {
                _browser = IE.AttachTo<IE>(Find.By("hwnd", _ieHwnd));
                _threadId = currentThreadId;
            }
            return _browser;
        }
        set
        {
            _browser = value;
            _ieHwnd = _browser.hWnd.ToString();
            _threadId = GetCurrentThreadId();
        }
    }

    /// <summary>
    /// private to prevent direct instantiation.
    /// </summary>
    private BrowserPool()
    {
        Browser = new IE();
    }

    /// <summary>
    /// Get the current executing thread's id.
    /// </summary>
    /// <returns>Thread Id.</returns>
    private int GetCurrentThreadId()
    {
        return Thread.CurrentThread.GetHashCode();
    }

    /// <summary>
    /// Accessor for instance
    /// </summary>
    public static BrowserPool Instance
    {
        get
        {
            return _instance;
        }
    }
}

现在进行测试:

  [TestMethod]
  public void Verify_Some_Useful_Thing()
  {
        var browser = BrowserPool.Instance.Browser;
        browser.GoTo("/someurl");
        // some assertions
  }

这很好,我的测试运行得很好现在,我不会每次测试都打开和关闭IE,因此速度更快。但是,我有一个问题,就是在测试完成后,我的IE实例仍然保持打开状态。

This works well and my tests run much faster now that I'm not opening and closing IE every test. However, I have this one problem in that when the tests complete my IE instance will still remain open.

我想不出一种优雅的方法来确保BrowserPool.Browser在应用程序结束之前调用了dispose()或close()。我什至尝试在BrowserPool类中使用终结器,但这似乎不起作用,因为调用终结器时_browser变量已被回收。

I can't figure out an elegant way to ensure that BrowserPool.Browser has dispose() or close() called on it before the application ends. I even tried using a finalizer in the BrowserPool class but that didn't seem to work because the _browser variable had already been reclaimed when my finalizer is called.

确保在测试运行后在我的IE实例上调用dispose()?

How can I ensure that dispose() is called on my IE instance after the test run?

推荐答案

使用 [AssemblyCleanupAttribute()] 到在组装中找到的测试完成后,清理资源。

Use the [AssemblyCleanupAttribute()] to clean resources after your tests found in the assembly are finished.

顺便说一句,永远不要依赖.NET中的析构函数。

Btw, never rely on the use of destructors in .NET.

这篇关于如何确保在应用程序关闭之前以单例方式处理对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆