最近做了一些WCF的项目,在客户端利用ChannelFactory创建一个Channel时会希望这个ServiceChannel在整个客户端中是唯一的。于是乎用了以下的代码,并一度为自己的聪明才智而欢欣鼓舞
代码
1 /// <summary>
2 /// service for Boss service action
3 /// </summary>
4 private IEBService _service;
5
6 /// <summary>
7 /// channel factories wich can create a channel for IEBService
8 /// </summary>
9 private ChannelFactory<IEBService> _channelFactory;
10
11 public IEBService Service
12 {
13 get
14 {
15 if (_service == null)
16 {
17 BasicHttpBinding binding = new BasicHttpBinding();
18 binding.MaxReceivedMessageSize = EBSettings.MessageCapacity;
19 binding.ReaderQuotas.MaxArrayLength = EBSettings.MessageCapacity;
20 binding.SendTimeout = TimeSpan.FromHours(1);
21 binding.ReceiveTimeout = TimeSpan.FromHours(1);
22 string serviceUrl = string.Format(EBSettings.EBServiceURLPattern, MachineName, EBSettings.EBServicePort);
23 this._channelFactory = new ChannelFactory<IEBService>(binding, serviceUrl);
24 _service = _channelFactory.CreateChannel();
25 }
26 return _service;
27 }
28 }
29
2 /// service for Boss service action
3 /// </summary>
4 private IEBService _service;
5
6 /// <summary>
7 /// channel factories wich can create a channel for IEBService
8 /// </summary>
9 private ChannelFactory<IEBService> _channelFactory;
10
11 public IEBService Service
12 {
13 get
14 {
15 if (_service == null)
16 {
17 BasicHttpBinding binding = new BasicHttpBinding();
18 binding.MaxReceivedMessageSize = EBSettings.MessageCapacity;
19 binding.ReaderQuotas.MaxArrayLength = EBSettings.MessageCapacity;
20 binding.SendTimeout = TimeSpan.FromHours(1);
21 binding.ReceiveTimeout = TimeSpan.FromHours(1);
22 string serviceUrl = string.Format(EBSettings.EBServiceURLPattern, MachineName, EBSettings.EBServicePort);
23 this._channelFactory = new ChannelFactory<IEBService>(binding, serviceUrl);
24 _service = _channelFactory.CreateChannel();
25 }
26 return _service;
27 }
28 }
29
后来才知道这就是传说中的Singleton 模式 ~~。更可悲的是我曾亲口对一个哥们说过:”Singleton模式?什么东西?“ 看来人不能傻到这种程度....
补课>>
代码
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace ConsoleApplication1
7 {
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 SingletonClass.Instance.Print(); // The way to call the instance
13 }
14 }
15
16 class SingletonClass
17 {
18 private SingletonClass()
19 {
20 // do nothing but override the contribute method to avoid new an instant outside this class
21 }
22
23 private static SingletonClass _instance = null;
24
25 /// <summary>
26 /// The only instance that use to return
27 /// </summary>
28 public static SingletonClass Instance
29 {
30 // Client can only access from here and this will make sure the same SingletonClass instance be returned
31 get
32 {
33 if (_instance == null)
34 {
35 _instance = new SingletonClass();
36 }
37 return _instance;
38 }
39
40 private set
41 {
42 }
43 }
44
45 public void Print()
46 {
47 Console.WriteLine("I'm the only instance of Singleton Class");
48 }
49 }
50 }
51
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace ConsoleApplication1
7 {
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 SingletonClass.Instance.Print(); // The way to call the instance
13 }
14 }
15
16 class SingletonClass
17 {
18 private SingletonClass()
19 {
20 // do nothing but override the contribute method to avoid new an instant outside this class
21 }
22
23 private static SingletonClass _instance = null;
24
25 /// <summary>
26 /// The only instance that use to return
27 /// </summary>
28 public static SingletonClass Instance
29 {
30 // Client can only access from here and this will make sure the same SingletonClass instance be returned
31 get
32 {
33 if (_instance == null)
34 {
35 _instance = new SingletonClass();
36 }
37 return _instance;
38 }
39
40 private set
41 {
42 }
43 }
44
45 public void Print()
46 {
47 Console.WriteLine("I'm the only instance of Singleton Class");
48 }
49 }
50 }
51
然而据可靠资料(MSDN)显示,这种做法在遇到多线程的时候会出现问题,即在当两个线程同时尝试创建该类的实例时,他们的初始条件(_instance == null)可能都符合,所以每个线程会试图去创建一个该类的实例。这种情况肯定是咱家不希望看到的,但是具体会出现啥样的情况需要以实践来检验。对此MSDN没有给出官方的说法~~,但是一种多线程下的Singleton模式也由此诞生了
代码
1 using System;
2
3 public sealed class Singleton
4 {
5 private static volatile Singleton instance;
6 private static object syncRoot = new Object();
7
8 private Singleton() {}
9
10 public static Singleton Instance
11 {
12 get
13 {
14 if (instance == null)
15 {
16 lock (syncRoot)
17 {
18 if (instance == null)
19 instance = new Singleton();
20 }
21 }
22
23 return instance;
24 }
25 }
26 }
27
2
3 public sealed class Singleton
4 {
5 private static volatile Singleton instance;
6 private static object syncRoot = new Object();
7
8 private Singleton() {}
9
10 public static Singleton Instance
11 {
12 get
13 {
14 if (instance == null)
15 {
16 lock (syncRoot)
17 {
18 if (instance == null)
19 instance = new Singleton();
20 }
21 }
22
23 return instance;
24 }
25 }
26 }
27
这段代码在实例化之前加了一把”锁“让跑在它后边的线程暂时进不来,也就解决了上一段代码所可能存在的问题。
官方资料给的很清楚,不翻译了