2014-06-07 19 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(); 
    } 


} 

Tôi đang cố mô phỏng một mẫu khởi chạy vòng lặp vô hạn mô phỏng cập nhật liên tục của trang web. Tôi bắt chước điều này với mô đun. Về lý thuyết tôi muốn điều này để hủy bỏ tất cả các nhiệm vụ xếp hàng theo semaphore và khởi động lại hàng đợi từ đầu nhưng nó dường như không làm điều đó. Ai đó có thể xin vui lòng bình luận về logic và mô hình của tôi?SemaphoreChuyển đổi mã hủy dịch vụ

đầu ra ngay bây giờ trông như thế này ::

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

Bạn có muốn các trang web được cập nhật song song hoặc từng trang một không? – i3arnon

+0

Tôi muốn họ cập nhật song song nhưng semaphore là để mô phỏng một mã mà cần phải có một khóa trên đó. – cubesnyc

+0

@YevgenyYurgenson, đây có phải là câu hỏi tiếp theo cho [câu hỏi trước của bạn] (http://stackoverflow.com/q/24020740/1768303) không? Điểm có 'SemaphoreSlim (1) 'là gì? Bạn không muốn có nhiều hơn 1 hoạt động cùng một lúc? – Noseratio

Trả lời

2

Vì vậy, tôi có một vài ý kiến, một số lỗi và một số chỉ gợi ý:

  1. Nếu tôi có thể, tôi thích kiểm tra hủy và kết thúc hoạt động, và không ném một ngoại lệ.
  2. updateasync void, thứ gần như không bao giờ xảy ra bên ngoài trình xử lý sự kiện. Bạn không thể quan sát lỗi và nó có thể gây ra vô số lỗi.
  3. Để song song các cập nhật trang web, hãy kích hoạt tất cả cập nhật và chỉ chờ một lần với Task.WhenAll
  4. Bạn đang gọi startup khi bất kỳ thao tác nào bị hủy. Điều đó có nghĩa là khi bạn hủy 5 trong số 10 cập nhật trang web, bạn sẽ khởi chạy 50 bản cập nhật trang web mới. Điều đó là không cần thiết.
  5. Chuyển một số CancellationToken đến SemaphoreSlim.WaitAsync chỉ quan sát việc hủy trong khi chờ đợi semaphore. bất kỳ hoạt động nào đã chạy sẽ không dừng lại. Đó có thực sự là ý định của bạn không? Một cách tiếp cận tốt hơn là kiểm tra mã thông báo trong khi cập nhật. Điều này có thể được mô phỏng bằng cách chuyển mã thông báo đến hoạt động Task.Delay.

Đây là cách tôi sẽ làm điều đó:

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(); 
     } 
    } 
} 

Tôi đã chia Task.Delay để làm cho nó nhiều hơn nữa tương tự, theo ý kiến ​​của tôi, để một trường hợp thực tế, nơi bạn có hoạt động khác nhau (tải về, phân tích cú pháp , lưu ví dụ) và bạn muốn truy vấn mã thông báo hủy giữa các bước đó.

Các vấn đề liên quan