我正在尝试在我的代码中使用线程,我在没有线程的解决方案中使用了这个代码。 我正在尝试在MS CRM中创建批量记录。有时记录数量非常高。
celery
但这需要花费太多时间来执行。因为每次调用“CreateRecordsAgainstContact”方法时,进程都会等待此方法执行。
所以我决定使用线程。
//Without Threading
foreach (EntityCollection col in RetrieveContactsFromStaticML(ConnectToCrm(),marketingListRecord))
{
CreateRecordsAgainstContact(_orgService, col, rewardDetails, errorLoger);
}
但我不确定:这是使用线程的最佳方式吗?
这是我的代码:
//With Threading
foreach (EntityCollection col in RetrieveContactsFromStaticML(ConnectToCrm(),marketingListRecord))
{
var t1 = Task.Factory.StartNew(delegate ()
{
CreateRecordsAgainstContact(_orgService, col, rewardDetails,errorLoger);
});
}
答案 0 :(得分:1)
这不起作用。并发执行任务不能共享相同的IOrganizationService
实例。您需要一个提供可重用服务实例的对象池。将池中的实例数限制为最多10个。
我建议使用BlockingCollection<T>
生产者消费者模式来安排需要完成的工作。 (见Blocking Collection and the Producer-Consumer Problem。)
答案 1 :(得分:0)
我想使用手动创建的线程并控制它的数量。在此示例中,有一个由多个线程处理的公共队列:
public class InsertBulkRecordsTask
{
private ConcurrentQueue<Contact> _contactsQueue;
public void Execute()
{
try
{
var contacts = RetrieveContactsFromStaticML(ConnectToCrm(), marketingListRecord);
_contactsQueue = new ConcurrentQueue<Contact>(contacts);
var threadsCount = AppConfigReader.ThreadsCount;
var threads = new List<Thread>();
for (int i = 0; i < threadsCount; i++)
threads.Add(new Thread(ProcessContactsQueue) { IsBackground = true });
threads.ForEach(r => r.Start());
threads.ForEach(r => r.Join());
}
catch (Exception ex)
{
// TODO: log
}
}
private void ProcessContactsQueue()
{
try
{
while (_contactsQueue.IsEmpty == false)
{
Contact contact;
if (_contactsQueue.TryDequeue(out contact) && contact != null)
{
try
{
// Save contact
}
catch (Exception ex)
{
// TODO: log
}
}
}
}
catch (Exception ex)
{
// TODO: log
}
}
}
答案 2 :(得分:0)
ExecuteMultipleRequest
适用于批量操作,我建议将其检出(并避免实施线程):
https://msdn.microsoft.com/en-us/library/jj863631.aspx
这是MSDN页面中提供的示例,它演示了多个创建请求:
// Get a reference to the organization service.
using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri,serverConfig.Credentials, serverConfig.DeviceCredentials))
{
// Enable early-bound type support to add/update entity records required for this sample.
_serviceProxy.EnableProxyTypes();
#region Execute Multiple with Results
// Create an ExecuteMultipleRequest object.
requestWithResults = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
// Create several (local, in memory) entities in a collection.
EntityCollection input = GetCollectionOfEntitiesToCreate();
// Add a CreateRequest for each entity to the request collection.
foreach (var entity in input.Entities)
{
CreateRequest createRequest = new CreateRequest { Target = entity };
requestWithResults.Requests.Add(createRequest);
}
// Execute all the requests in the request collection using a single web method call.
ExecuteMultipleResponse responseWithResults =
(ExecuteMultipleResponse)_serviceProxy.Execute(requestWithResults);