3

我正在使用 Thread.Join 在新线程中启动某些功能。

不幸的是,我在部分代码中遇到了运行时错误,这里是:

    IBuyerRequest NewRequest(string className)
    {
        className.ThrowNullOrEmpty("className");

        var type = Type.GetType(string.Format("MyApplication.BLL.PingtreeEngine.Requests.{0}Request", className));
        object[] args = { _appForm };

        type.ThrowNull("type");

        var instance = Activator.CreateInstance(type, args) as IBuyerRequest;

        return instance;
    }

Activator.CreateInstance 导致错误是“异常已被调用的目标抛出”。

有人知道我如何解决这个问题吗?

4

1 回答 1

2

问题是您尝试激活的类可能正在尝试使用 HttpContext.Current,它在后台线程中不存在,因为它保存在线程本地存储中。

我假设你正在做这样的事情:

    public void StartBackgroundRequest()
    {
        var thread = new Thread(StartMethod);
        thread.Start();
    }

    private void StartMethod()
    {
        //bunch of stuff
        var request = NewRequest(className); // exception gets throw here
    }

您需要对此进行更改,以便它在请求线程上捕获 HttpContext 并将其设置在您的后台线程上,然后再激活类型:

    public void StartBackgroundRequest()
    {
        var thread = new Thread(StartMethod);
        thread.Start(HttpContext.Current);
    }

    private void StartMethod(object state)
    {
        HttpContext.Current = (HttpContext)state;

        //bunch of stuff
        var request = NewRequest(className); // exception gets throw here
    }

我应该注意,您正在激活的组件的实现可能存在其他细微差别,这可能意味着它在多线程环境中表现不佳,我不知道。

同样值得注意的是,IIS/ASP.NET 线程/进程模型可能有点复杂,因此您可能希望也可能不希望在后台线程上实际执行此操作,具体取决于您的要求。例如,当没有更多未完成的请求时,IIS 可以回收进程,但您的后台线程可能仍在运行。如果我需要运行需要运行完成的后台任务,我通常会将该功能拆分为单独的 Windows 服务或类似服务,并将这些任务代理给它,以便我更好地控制进程和线程。

于 2013-08-15T17:52:41.400 回答