5

我需要一些 Elmah 登录在我的网络服务器上执行的异步任务。但是当我尝试记录错误时,它会因为 HttpContext 而失败。

        var httpContext = HttpContext.Current;

        Task.Factory.StartNew(() =>
        {
            HttpContext.Current = httpContext;

            try
            {
                //Execute some code
            }
            catch (Exception ex)
            {
                //Generate some error for the user and log the error in Elmah
                try
                {
                    ErrorLog.GetDefault(HttpContext.Current).Log(new Error(ex));
                }
                catch(Exception ex)
                {
                }
            }
        });

为了获得任务的进展,我实施了一些轮询机制。目前没有任何错误记录到 Elmah,这使得解决它们变得困难。

同样提供上下文作为参数也不起作用。

它不起作用。我收到一个 ArgumentException,告诉我预期值不在预期范围内。使用以下堆栈跟踪:

在 System.Web.Hosting.IIS7WorkerRequest.GetServerVariableInternal(String name) 在 System.Web.HttpRequest.AddServerVariableToCollection(String name) 在 System.Web.HttpRequest 的 System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)。 FillInServerVariablesCollection() 在 System.Web.HttpServerVarsCollection.Populate() 在 System.Web.HttpServerVarsCollection.Get(String name) 在 Elmah.ErrorLog.InferApplicationName(HttpContext context) 在 Elmah.ErrorLog.GetDefaultImpl(HttpContext context) 在 Elmah.ServiceContainer。 GetService(Type serviceType) at Elmah.ServiceCenter.GetService(Object context, Type serviceType) at Elmah.ErrorLog.GetDefault(HttpContext context) at Bis.Utilities.Log.ElmahErrorLog.TryLogError(Exception exeption) in D:\Users\A500535\Documents\Projecten\Biobank\Bis\src\Utilities\Log\ElmahErrorLog.cs:第 13 行

4

2 回答 2

5

下面是一个可以完成工作的丑陋黑客。本质上,它Error在伪造Exception的(原型)上创建一个对象,以便可以在请求仍在进行中时捕获上下文。稍后,当由于请求失败而启动的任务时,会根据发生Error的实际异常创建另一个对象,然后有选择地从早期原型中复制有趣的上下文位。Error不幸的是,无论是否发生异常,都必须创建原型。

// Create an error that will capture the context
// and serve as a prototype in case a real exception
// needs logging

var prototype = new Error(new Exception(), context);

Task.Factory.StartNew(() =>
{
    try
    {
        // Execute some code
    }
    catch (Exception ex)
    {
        // Generate some error for the user and log the error in ELMAH
        try
        {
            // Create a new error without contextual information
            // but then copy over the interesting bits from the
            // prototype capture at time of request.

            var error = new Error(ex)
            {
                HostName = prototype.HostName,
                User = prototype.User,
            };
            error.ServerVariables.Add(prototype.ServerVariables);
            error.QueryString.Add(prototype.QueryString);
            error.Cookies.Add(prototype.Cookies);
            error.Form.Add(prototype.Form);
            ErrorLog.GetDefault(null).Log(error);
        }
        catch(Exception)
        {
        }
    }
});
于 2012-08-13T13:39:36.907 回答
2

当您启动一个新线程时,它不会获得 HttpContext 结构。由于 Elmah 日志记录需要 HttpContext 数据,因此它会失败。

请参阅以下 QA: Elmah 不会在火灾中发送电子邮件而忘记情况

对我来说,这在一个名为 Task.Run 的异步任务中工作:

Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new NotSupportedException("elmah logging test")));
于 2015-07-08T08:54:06.327 回答