2014-06-07 8 views
5
class Program 
{ 
    static IEnumerable<site> list = Enumerable.Range(1, 10).Select(i => new site(i.ToString())); 

    static void Main(string[] args) 
    { 
     startup(); 
     Console.ReadKey(); 
    } 

    static public void startup() 
    { 
     router.cts = new CancellationTokenSource(); 

     foreach (var s in list) 
     { 
      update(s); 
     } 
    } 

    async static public void update(site s) 
    { 
     try 
     { 
      while (true) 
      { 
       await s.Refresh(); 
       if (site.count % 4 == 0) 
       { 
        Console.WriteLine("Reseting Queue"); 
        router.cts.Cancel(); 
       } 
      } 
     } 
     catch (OperationCanceledException) 
     { 
      Console.WriteLine("Canceled"); 
      startup(); 
     } 
    } 
} 

class router 
{ 
    public static SemaphoreSlim ss = new SemaphoreSlim(1); 
    public static CancellationTokenSource cts { get; set; } 


} 

class site 
{ 
    public static int count = 0; 
    public string sitename {get; set;} 

    public site(string s) 
    { 
     sitename = s; 
    } 

    async public Task Refresh() 
    { 
     await router.ss.WaitAsync(router.cts.Token); 
     //Console.WriteLine("{0}:: Start Refreshing ", sitename); 
     await Task.Delay(1000); 

     Console.WriteLine("{0}:: Done Refreshing ", sitename); 
     count++; 
     router.ss.Release(); 
    } 


} 

मैं एक ऐसे पैटर्न की नकल करने की कोशिश कर रहा हूं जो अनन्त लॉन्च करता है जबकि लूप जो साइट के निरंतर अद्यतन को अनुकरण करता है। मैं मॉड्यूलस के साथ नकल कर रहा हूँ। सिद्धांत रूप में मैं इसे सैमफोर द्वारा कतारबद्ध सभी कार्यों को रद्द करना चाहता हूं और शुरुआत से कतार को पुनरारंभ करना चाहता हूं लेकिन ऐसा लगता है कि ऐसा नहीं लगता है। क्या कोई मेरे तर्क और पैटर्न पर टिप्पणी कर सकता है?सेमफोरस्लिम रद्दीकरण टोकन

उत्पादन अभी इस ::

1:: Done Refreshing 
2:: Done Refreshing 
3:: Done Refreshing 
4:: Done Refreshing 
Reseting Queue 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
5:: Done Refreshing 
1:: Done Refreshing 
2:: Done Refreshing 
3:: Done Refreshing 
Reseting Queue 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
4:: Done Refreshing 
5:: Done Refreshing 
6:: Done Refreshing 
7:: Done Refreshing 
Reseting Queue 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
Canceled 
8:: Done Refreshing 
9:: Done Refreshing 
10:: Done Refreshing 
1:: Done Refreshing 
Reseting Queue 
Canceled 
+0

क्या आप साइट को समानांतर में या एक-एक करके अपडेट करना चाहते हैं? – i3arnon

+0

मैं चाहता हूं कि वे समानांतर में अपडेट करें लेकिन सेमफोर उस कोड को अनुकरण करना है जिस पर लॉक होना आवश्यक है। – cubesnyc

+0

@YevgenyYurgenson, क्या यह आपके [पिछले प्रश्न] (http://stackoverflow.com/q/24020740/1768303) का अनुवर्ती है? 'सेमफोरस्लिम (1)' होने का क्या मतलब है? क्या आप एक ही समय में 1 से अधिक ऑपरेशन नहीं करना चाहते हैं? – Noseratio

उत्तर

2

तो की तरह लग रहा है, मैं कई टिप्पणी है, कुछ कीड़े और कुछ सिर्फ सुझाव हैं:

  1. अगर मैं कर सकते हैं, मैं रद्द करने के लिए जाँच पसंद करते हैं और ऑपरेशन समाप्त, और एक अपवाद फेंक नहीं।
  2. updateasync void है, जो किसी ईवेंट हैंडलर के बाहर लगभग कभी नहीं होना चाहिए। आप त्रुटियों का पालन नहीं कर सकते हैं और यह असंख्य बग का कारण बन सकता है।
  3. साइट अपडेट parallelize, सभी अद्यतन आग और केवल Task.WhenAll
  4. आप startup बुला रहे हैं जब किसी भी कार्रवाई रद्द कर दी है के साथ एक बार का इंतजार करने के लिए। इसका मतलब है कि जब आप 10 साइट अपडेट में से 5 को रद्द कर देते हैं तो आप 50 नए साइट अपडेट लॉन्च कर रहे हैं। यह अनावश्यक है।
  5. CancellationToken को SemaphoreSlim.WaitAsync पर पास करना केवल सेमफोर की प्रतीक्षा करते समय रद्दीकरण को देखता है। पहले से चल रहा कोई भी ऑपरेशन बंद नहीं होगा। क्या यह वास्तव में आपका इरादा है? अपडेट करते समय टोकन को जांचना बेहतर होगा। इसे Task.Delay ऑपरेशन में टोकन पास करके अनुकरण किया जा सकता है।

यहां बताया गया है मैं यह किया होता है:

class Program 
{ 
    static IEnumerable<site> list = Enumerable.Range(1, 10).Select(i => new site(i.ToString())); 

    static void Main(string[] args) 
    { 
     Startup().Wait(); 
     Console.ReadKey(); 
    } 

    static async Task Startup() 
    { 
     while (true) 
     { 
      router.cts = new CancellationTokenSource(); 

      await Task.WhenAll(list.Select(s => Update(s))); 
     } 
    } 

    static Task Update(site s) 
    { 
     if (site.count % 4 == 0) 
     { 
      Console.WriteLine("Reseting Queue"); 
      router.cts.Cancel(); 
     } 
     else 
     { 
      return s.Refresh(); 
     } 
    } 
} 

class router 
{ 
    public static SemaphoreSlim ss = new SemaphoreSlim(1); 
    public static CancellationTokenSource cts { get; set; } 
} 

class site 
{ 
    public static int count = 0; 
    public string sitename {get; set;} 

    public site(string s) 
    { 
     sitename = s; 
    } 

    public async Task Refresh() 
    { 
     await router.ss.WaitAsync(); 
     try 
     { 
      if (router.cts.token.IsCancellationRequested) 
      { 
       return; 
      } 
      await Task.Delay(500); 

      if (router.cts.token.IsCancellationRequested) 
      { 
       return; 
      } 
      await Task.Delay(500); 

      Console.WriteLine("{0}:: Done Refreshing ", sitename); 
      count++; 
     } 
     finally 
     { 
      router.ss.Release(); 
     } 
    } 
} 

मैं Task.Delay विभाजित किया है इसे और अधिक समान बनाने के लिए, मेरी राय में, एक असली मामले में जहां आप कई विभिन्न कार्यों (डाउनलोड करने के लिए, पार्स , उदाहरण के लिए सहेजें) और आप उन चरणों के बीच रद्दीकरण टोकन से पूछना चाहते हैं।

संबंधित मुद्दे