在实时项目中使用线程的最佳实践?

时间:2017-07-21 12:13:39

标签: c# multithreading dynamics-crm

我正在尝试在我的代码中使用线程,我在没有线程的解决方案中使用了这个代码。 我正在尝试在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);
});

}

3 个答案:

答案 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);

完整示例在https://msdn.microsoft.com/en-us/library/jj863604.aspx