【问题标题】:Apply [ThreadStatic] attribute to a method in external assembly将 [ThreadStatic] 属性应用于外部程序集中的方法
【发布时间】:2013-10-28 15:52:37
【问题描述】:

我可以像[ThreadStatic] 一样使用外部程序集的static method 方法吗?

这是我的情况。 assembly class(我无法访问其源代码)具有这种结构

public class RegistrationManager()
{
    private RegistrationManager() {}
    public static void RegisterConfiguration(int ID) {}
    public static object DoWork() {}
    public static void UnregisterConfiguration(int ID) {}
}

注册后,如果不取消注册之前注册的 ID,我就无法使用其他 ID 呼叫 DoWork()。实际上我想通过多线程同时调用具有不同 ID 的 DoWork() 方法。

如果RegisterConfiguration(int ID) 方法是[ThreadStatic],我可以在不同的线程中调用它而不会出现调用问题,对吧?那么,我可以将[ThreadStatic] 属性应用于此方法还是有其他方法可以同时调用两个static 方法而无需等待其他线程注销它?


如果我像下面这样检查它,它应该可以工作。

for(int i=0; i < 10; i++)
{
    new Thread(new ThreadStart(() => Checker(i))).Start();
}

public string Checker(int i)
{
    public static void RegisterConfiguration(i); // Now i cannot register second time
    public static object DoWork(i);
    Thread.Sleep(5000); // DoWork() may take a little while to complete before unregistered
    public static void UnregisterConfiguration(i);
}

【问题讨论】:

    标签: c# multithreading thread-safety static-methods threadstatic


    【解决方案1】:

    我不知道您可以将[ThreadStatic] 添加到外部程序集中,而无需重新编译源代码。

    但是,您可以创建额外的应用程序域来同时执行代码。不像线程那么优雅,但仍然是一种潜在的解决方案。

    http://msdn.microsoft.com/en-us/library/ms173139%28v=VS.100%29.aspx

    根据您可能绑定的许可证,另一个选项是使用use a tool like Reflector 对外部程序集的源代码进行反向工程并添加[ThreadStatic] 属性。

    【讨论】:

    • 谢谢 Erik,我会尝试使用不同的应用程序域。我发现this question与此相关,但是我在不同的AppDomains中调用静态方法时感到困惑,让我试试。
    • 对您引用的问题的接受答案应该可以解决问题。您首先需要创建一个包装器对象,您可以创建一个实例,并让该包装器对象与静态方法交互。让我知道结果如何。
    • 我尝试使用另一个包装库并调用该函数,它调用了该函数,但由于它返回另一个对象,该对象是外部库中不可序列化类的实例。所以我得到了一个序列化异常。当我们调用appDomain1..CreateInstanceAndUnwrap(...).FactoryMethod() 时,是否有创建一个不可序列化的对象并从包装库中返回它?
    【解决方案2】:

    ThreadStatic 适用于字段,而不是方法,所以这个想法从一开始就注定了。应该可以反汇编 dll,修改源代码并重新组装,但这没有实际意义,因为没有简单的方法可以使另一个组件成为线程安全的。

    你可能想写一个像这样的包装类:

    class RegistraionWrapper
    {
        private static Object _lock = new Object();
    
        public static void DoWork(int ID)
        {
            lock (_lock)
            {
                RegistrationManager.RegisterConfiguration(ID);
                RegistrationManager.DoWork();
                RegistrationManager.UnregisterConfiguration(ID);
            }
        }
    }
    

    您可能需要将 Unregister 调用放在 finally 块中。当然,锁使得生成多个线程来完成工作变得毫无意义,但不清楚这个库是否支持这一点。最好的办法是与这个库的作者交谈。

    【讨论】:

      猜你喜欢
      • 2020-11-14
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 2015-01-23
      • 2015-04-03
      • 2012-01-06
      • 2021-09-29
      • 1970-01-01
      相关资源
      最近更新 更多