2008-10-23 28 views
14

Tôi đang cố gắng thực hiện một số công cụ không đồng bộ trong phương thức webservice. Giả sử tôi có lệnh gọi API sau: http://www.example.com/api.asmxDịch vụ Web .NET & Chủ đề nềnWorker

và phương thức được gọi là GetProducts().

Tôi phương pháp GetProducts này, tôi làm một số công cụ (ví dụ: lấy dữ liệu từ cơ sở dữ liệu), ngay trước khi tôi trả lại kết quả, tôi muốn thực hiện một số công cụ async (ví dụ: gửi cho tôi email).

Vì vậy, đây là những gì tôi đã làm.

[WebMethod(Description = "Bal blah blah.")] 
public IList<Product> GetProducts() 
{ 
    // Blah blah blah .. 
    // Get data from DB .. hi DB! 
    // var myData = ....... 
    // Moar clbuttic blahs :) (yes, google for clbuttic if you don't know what that is) 

    // Ok .. now send me an email for no particular reason, but to prove that async stuff works. 
    var myObject = new MyObject(); 
    myObject.SendDataAsync(); 

    // Ok, now return the result. 
    return myData; 
    } 
} 

public class TrackingCode 
{ 
    public void SendDataAsync() 
    { 
     var backgroundWorker = new BackgroundWorker(); 
     backgroundWorker.DoWork += BackgroundWorker_DoWork; 
     backgroundWorker.RunWorkerAsync(); 
     //System.Threading.Thread.Sleep(1000 * 20); 
    } 

    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     SendEmail(); 
    } 
} 

Bây giờ, khi tôi chạy mã này, email sẽ không bao giờ được gửi. Nếu tôi uncomment ra Thread.Sleep .. sau đó email được gửi đi.

Vậy ... tại sao chuỗi công nhân nền bị rách? là nó phụ thuộc vào thread cha? Đây có phải là cách sai tôi nên làm nền hoặc chia hai luồng, trong các ứng dụng web asp.net?

Trả lời

17

BackgroundWorker hữu ích khi bạn cần đồng bộ hóa lại (ví dụ) một chuỗi giao diện người dùng *, ví dụ: vì các lý do liên quan. Trong trường hợp này, có vẻ như chỉ đơn giản là sử dụng ThreadPool sẽ là quá đủ (và đơn giản hơn nhiều). Nếu bạn có số lượng lớn, sau đó một hàng đợi nhà sản xuất/tiêu dùng có thể cho phép throttling tốt hơn (do đó bạn không bị chết đuối trong bài) - nhưng tôi nghi ngờ ThreadPool sẽ ổn ở đây ...

public void SendDataAsync() 
{ 
    ThreadPool.QueueUserWorkItem(delegate 
    { 
     SendEmail(); 
    }); 
} 

Ngoài ra - Tôi không hoàn toàn chắc chắn những gì bạn muốn đạt được bằng cách ngủ? Điều này sẽ chỉ tie lên một sợi (không sử dụng CPU, nhưng không làm tốt hoặc). Chăm sóc để xây dựng? Nó trông giống như bạn đang tạm dừng trang web thực sự của bạn (tức là chế độ Ngủ xảy ra trên chuỗi trang web, không phải là chuỗi email). Bạn đang cố gắng làm gì ở đây?

* = trên thực tế, nó sẽ sử dụng bất cứ đồng bộ bối cảnh được đặt ra

+0

Giấc ngủ được nhận xét. Tôi đặt nó ở đó để xem tôi có thể gửi email không. khi giấc ngủ được CHẤP NHẬN, thì mã chuỗi công nhân nền được thực thi. khi mã được tạo ra, thì mã chuỗi công nhân nền không bao giờ được thực thi. Tôi sẽ thử sử dụng ThreadPool thay thế. –

+0

> * Nếu bạn có khối lượng lớn, sau đó một nhà sản xuất/hàng tiêu dùng có thể cho phép điều chỉnh tốt hơn (vì vậy bạn không bị chết đuối trong chủ đề) * ooooooo !!!Tôi vui vì bạn đã thực sự nêu lên điểm này! phương pháp dịch vụ web thực sự là khối lượng cao! Ngoài ra, để làm cho vấn đề thực sự thú vị, nó không thực sự gửi một email, nhưng thực sự nhấn một trang web bên ngoài (ekk, không hỏi) ... vì vậy bạn sẽ đề nghị tôi làm điều này nhà sản xuất/hàng tiêu dùng thingy? Nếu vậy ... đây có phải là trang tốt để tham khảo không? http://www.albahari.com/threading/part4.aspx (vui lòng cuộn xuống một chút công bằng để viết mã + ví dụ). suy nghĩ? –

+0

@Marc Gravell Tôi đã thử sử dụng giải pháp của bạn nhưng tôi chỉ tự hỏi tại sao phải mất quá nhiều thời gian để hoàn thành nhiệm vụ. – AnandMohanAwasthi

0

Nó có thể bị rách xuống vì sau 20 giây, mà BackgroundWorker dụ có thể được thu gom rác vì nó không có tài liệu tham khảo (đi ra khỏi phạm vi).

+0

Lưu ý rằng Sleep() nằm trên chuỗi trang web; có nhiều khả năng là BackgroundWorker đang cố gắng sử dụng bối cảnh đồng bộ hóa bị chặn bởi chính Sleep() –

1

Tái sản xuất/người tiêu dùng; về cơ bản - nó chỉ là giá trị giữ một số loại loại ga. Ở mức đơn giản nhất, có thể sử dụng Semaphore (cùng với số ThreadPool thông thường) để giới hạn mọi thứ với số lượng công việc đã biết (để tránh bão hòa hồ bơi luồng); nhưng một nhà sản xuất/hàng tiêu dùng có thể sẽ hiệu quả hơn và được quản lý hơn.

Jon Skeet có hàng đợi như vậy here (CustomThreadPool). Tôi có thể viết một số ghi chú về nó nếu bạn muốn.

Điều đó nói rằng: nếu bạn đang gọi đến một trang web bên ngoài, rất có khả năng bạn sẽ có rất nhiều sự chờ đợi trên mạng IO/cổng hoàn tất; như vậy, bạn có thể có một số lượng cao hơn một chút của chủ đề ... rõ ràng (ngược lại) nếu công việc được CPU-ràng buộc, không có điểm có chủ đề nhiều hơn bạn có lõi CPU.

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