在另一个Thread中使用SSRS Webservice

时间:2009-03-05 06:10:51

标签: c# asp.net web-services multithreading reporting-services

我从asp.net应用程序内部调用SQL Server Reporting Services Web服务。我需要关闭给定报告的所有订阅。但是我不希望用户必须等待它发生所有事情,所以我希望将所有webservice调用放在一个单独的线程中,并立即返回给用户。

我正在使用看起来像这样的代码:

public static void FireAllAsync(string ReportPath)
{
    Hashtable paramValues = new Hashtable();
    ThreadPool.QueueUserWorkItem(new WaitCallback(FireAll), ReportPath);
}

public static void FireAll(object ReportPath)
{

    ReportingService rs = new ReportingService();
    rs.Credentials = System.Net.CredentialCache.DefaultCredentials;

    Subscription[] SubList = rs.ListSubscriptions((string)ReportPath, null);

    foreach (Subscription CurSub in SubList) {
        rs.FireEvent(CurSub.EventType, CurSub.SubscriptionID);
    }

}

调用FireAll工作正常,但尝试调用FireAllAsync以使用线程失败并显示401错误。我相信凭证的问题没有得到正确的传递。即这行代码:

rs.Credentials = System.Net.CredentialCache.DefaultCredentials;

我不太了解凭证缓存的工作原理,所以我无法弄清楚为什么它不喜欢在一个单独的线程中。

我试过抓取外部函数中的凭据,并将它们作为参数传递,但是会发生同样的错误。

有没有人对可能发生的事情有任何想法?

1 个答案:

答案 0 :(得分:3)

当您的主线程正在执行时,它会为其准备一个模拟上下文。在经过身份验证的方案中,IIS已对用户进行身份验证,然后为该用户设置线程令牌 - 而不是进程令牌。

因为为用户设置了线程令牌,所以该线程可以代表用户行事(在本地盒子上;代表另一个盒子上的用户行动需要设置委托如果使用集成Windows身份验证(NTLM / Kerberos),则为up。

但是,如果您在没有任何身份信息的情况下分离工作线程,那么该工作线程将在没有自己的令牌的情况下生成,因此它将使用进程令牌。

如果您可以在初始线程上执行您需要执行的操作,则不会出现委派问题,只是工作线程上缺少用户令牌。

Threadpool线程将作为进程标识运行(默认情况下为NetworkService,因此托管计算机的计算机帐户,除非您的应用程序池设置为以SomeUser运行,在这种情况下,所有工作线程将作为SomeUser运行) - 如果该用户可以访问初始用户想要的任何内容,一切都很好。

如果没有,401sville。

有一些网络参考可以帮助解决这个问题,并提供各种可能的答案:

http://geekswithblogs.net/khanna/archive/2005/02/09/22441.aspx

http://aspalliance.com/articleViewer.aspx?aId=650&pId=2