Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的静态方法、静态字段和多标题#_C#_.net_Multithreading - Fatal编程技术网

C# C语言中的静态方法、静态字段和多标题#

C# C语言中的静态方法、静态字段和多标题#,c#,.net,multithreading,C#,.net,Multithreading,我有一个静态类和一个字段以及其中的两个方法: static class MyClass{ private static HttpClient client = new HttpClient(); private static string SendRequestToServer(int id) { Task<HttpResponseMessage> response = client.GetAsync("some st

我有一个静态类和一个字段以及其中的两个方法:

 static class MyClass{

       private static HttpClient client = new HttpClient();
       private static string SendRequestToServer(int id)
       {
          Task<HttpResponseMessage> response = client.GetAsync("some string");
          responseTask.ContinueWith(x => PrintResult(x));
          return "some new value";
        }

        private static void Print(Task<HttpResponseMessage> task)
        {
            Task<string> r = task.Result.Content.ReadAsStringAsync();
            r.ContinueWith(resultTask => Console.WriteLine("result is: " + resultTask.Result));
        }
 }
静态类MyClass{
私有静态HttpClient=新HttpClient();
私有静态字符串SendRequestToServer(int id)
{
任务响应=client.GetAsync(“某些字符串”);
responseTask.ContinueWith(x=>PrintResult(x));
返回“一些新值”;
}
专用静态无效打印(任务)
{
Task r=Task.Result.Content.ReadAsStringAsync();
r、 ContinueWith(resultTask=>Console.WriteLine(“结果是:”+resultTask.result));
}
}

问题是,如果许多线程开始使用MyClass及其方法,是否会导致一些问题?

通过这些方法访问的所有资源都需要是线程安全的。在你的情况下,他们不是。如果您查看文档,它会指出:

此类型的任何公共静态(在Visual Basic中共享)成员都是线程安全的不保证任何实例成员是线程安全的

您正在调用一个实例方法(
client.GetAsync
),该方法不能保证线程安全,因此可能会给您带来问题

为了缓解这种情况,您可以:

  • 在每次调用时创建一个新的(本地)
    HttpClient
  • 同步对
    客户端的访问(例如使用锁)

另外,我无法告诉您
PrintResult
是否是线程安全的,但是控制台.WriteLine应该是线程安全的。

这样的设置可能会产生不可预测的结果。您需要让线程以同步的方式访问数据。在您的案例中需要使用语句,以确保以同步和稳定的方式执行

private static Object locker= new Object();

private static string SendRequestToServer(int id)
{ 
  lock(locker)
  {
    Task<HttpResponseMessage> response = client.GetAsync("some string");
    responseTask.ContinueWith(x => PrintResult(x));
    return "some new value";
  }
}
private static Object locker=new Object();
私有静态字符串SendRequestToServer(int id)
{ 
锁(储物柜)
{
任务响应=client.GetAsync(“某些字符串”);
responseTask.ContinueWith(x=>PrintResult(x));
返回“一些新值”;
}
}

考虑到您的应用程序可能在多台web计算机上运行,在web应用程序中使用静态字段很棘手。这正是在web应用程序中使用静态字段时应该记住的:)为什么locker应该是静态的?如果MyClass不是静态的,那么
locker
也可以是实例变量吗?是的,如果您的类不是静态的,那么它可以是实例变量真的吗?如果许多不同的线程开始调用SendRequestToServer(),那么就没有任何理由使用lock(locker),因为每个线程都有自己的
locker
对象副本。使用lock会让我有点困惑。locker对象必须是静态变量还是intance变量?请参阅@CodeIgnoto示例。它是静态字段还是实例字段并不直接重要——重要的是进入锁的线程使用相同的对象引用。当您使用实例字段时,所有调用者都将获得自己的引用,所以这不起作用,对吗?:)因此,为了同步静态方法,需要锁定静态字段。在您的情况下,您已经有了这样一个对象,客户机。您可以简单地锁定客户端。您确实不需要单独的锁对象,但SendRequestToServer是一个实例方法,如果locker是一个实例变量,它会是线程安全的吗?我不这么认为,因为每个线程都有自己的locker副本。是的,那么它就不是线程安全的,因为即使它是一个实例方法,它仍然访问实例之间共享的静态对象(客户端)。因此,您仍然需要一个静态对象来锁定。