我有一個應用程序通知我們的SMS數據庫中的每個用戶更新我們的系統。它使用實體框架來選擇每條記錄,然後創建一個新的任務來向該人發送消息。從理論上講,這應該是一個快速的過程。我做錯了什麼,因爲它每一秒或兩秒只能得到一次完整的迴應。使用Task.Factory和Entity Framework的多線程?
我認爲這個問題與我在Task.Factory.StartNew()
中設置任務的方式有關。它表現得像是在同步運行,但我希望它能夠異步運行。
如果我完全脫離了我如何使用任務的基礎,請告訴我。我從this post得到了我的靈感。
這裏是我的代碼:
class Program
{
static List<MessageToSend> Messages = new List<MessageToSend>();
static Entities oDatabase = new Entities();
static SMS.API oAPI = new SMS.API();
const string sAuthToken = "*****";
const string sNotificationMessage = "*****";
static void Main(string[] args)
{
foreach (var subscriber in oDatabase.SMS_Subscribers.Where(x => x.GlobalOptOut == false))
{
MessageToSend oMessage = new MessageToSend();
oMessage.ID = subscriber.ID;
oMessage.MobileNumber = subscriber.MobileNumber;
var recentlySentMessage = oDatabase.SMS_OutgoingMessages.Where(x => x.Message == sNotificationMessage && x.MobileNumber == oMessage.MobileNumber && x.Sent > new DateTime(2014, 3, 12)).FirstOrDefault();
if (recentlySentMessage != null)
{
oMessage.Completed = true;
continue;
}
Task t = Task.Factory.StartNew(() =>
{
try{
var keywordID = oDatabase.SMS_SubscribersKeywords.Where(x => x.SubscriberID == oMessage.ID).First().KeywordID;
var keyword = oDatabase.SMS_Keywords.Where(x => x.ID == keywordID).First();
oMessage.DemographicID = keyword.DemographicID;
oMessage.Keyword = keyword.Keyword;
SendNotificationMessage(oMessage);
}
catch (Exception oEx){ //Write exception to console}
});
Thread.Sleep(15);
}
while (Messages.ToList().Any(x => !x.Completed)){ //wait till all are completed}
}
public static void SendNotificationMessage(object message)
{
MessageToSend oMessage = (MessageToSend)message;
try
{
SMS.APIResponse oResponse = oAPI.SendMessage(sAuthToken, oMessage.DemographicID, oMessage.Keyword, oMessage.MobileNumber, sNotificationMessage);
if (oResponse.Success){ //Write success to console }
else{ //Write failure to console }
}
catch (Exception oEx){ //Write Exception to console }
oMessage.Completed = true;
}
}
class MessageToSend
{
public long ID { get; set; }
public long DemographicID {get;set;}
public string MobileNumber { get; set; }
public bool Completed { get; set; }
public string Keyword { get; set; }
public MessageToSend(){ Completed = false; }
}
編輯:在foreach塊的內部現在看起來是這樣的:
MessageToSend oMessage = new MessageToSend();
oMessage.ID = subscriber.ID;
oMessage.MobileNumber = subscriber.MobileNumber;
int keywordID = 0;
SMSShortcodeMover.SMS_Keywords keyword;
var recentlySentMessage = oDatabase.SMS_OutgoingMessages.Where(x => x.Message == sNotificationMessage && x.MobileNumber == oMessage.MobileNumber && x.Sent > new DateTime(2014, 3, 12)).FirstOrDefault();
if (recentlySentMessage != null)
{
oMessage.Completed = true;
continue;
}
try
{
keywordID = (int)oDatabase.SMS_SubscribersKeywords.Where(x => x.SubscriberID == oMessage.ID).First().KeywordID;
keyword = oDatabase.SMS_Keywords.Where(x => x.ID == keywordID).First();
} catch (Exception oEx){ //write exception to console, then continue; }
Task t = Task.Factory.StartNew(() =>
{
oMessage.DemographicID = keyword.DemographicID;
oMessage.Keyword = keyword.Keyword;
SendNotificationMessage(oMessage);
});
Thread.Sleep(15);
}
編輯2: 我再次更新我的代碼,我現在收集所有的我的數據在我進入發送之前。它仍然掛在某個地方,但它現在可以在大約5秒內獲得所有52,000行數據。代碼如下所示:
var query =
(from subscriber in oDatabase.SMS_Subscribers
where subscriber.GlobalOptOut == false
where !(from x in oDatabase.SMS_OutgoingMessages
where x.Message == sNotificationMessage
where x.MobileNumber == subscriber.MobileNumber
where x.Sent > new DateTime(2014, 3, 12)
select x).Any()
join sk in oDatabase.SMS_SubscribersKeywords
on subscriber.ID equals sk.SubscriberID
join k in oDatabase.SMS_Keywords on sk.KeywordID equals k.ID into ks
from k2 in ks.Take(1)
select new MessageToSend()
{
ID = subscriber.ID,
MobileNumber = subscriber.MobileNumber,
DemographicID = k2.DemographicID,
Keyword = k2.Keyword
}).ToList();
foreach(var q in query){
Task t = Task.Factory.StartNew(() => SendNotificationMessage(q));
Tasks.Add(t);
Thread.Sleep(80);
}
Task.WaitAll(Tasks.ToArray());
首先,嘗試在任務外執行oDatabase查詢。另外爲什麼你的代碼有一個'Thread.Sleep(15)'? – Enigmativity
我有一個'Thread.Sleep(15)'來限制循環的速度。我們允許我們的SMS提供商產生多少流量是有限制的。 我最初在任務外部有'oDatabase'查詢,但是我把它們放在裏面去試圖阻止它們阻塞代碼的其餘部分。不過,它似乎沒有幫助。 – ijb109