Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在实时项目中使用线程的最佳实践?_C#_Multithreading_Dynamics Crm - Fatal编程技术网

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

C# 在实时项目中使用线程的最佳实践?,c#,multithreading,dynamics-crm,C#,Multithreading,Dynamics Crm,我试图在我的代码中使用线程,我在解决方案中使用了这段代码而没有使用线程。 我正在尝试在MS CRM中创建批量记录。有时,记录的数量会非常高 //Without Threading foreach (EntityCollection col in RetrieveContactsFromStaticML(ConnectToCrm(),marketingListRecord)) { CreateRecordsAgainstContact(_orgService, col, rewardDeta

我试图在我的代码中使用线程,我在解决方案中使用了这段代码而没有使用线程。 我正在尝试在MS CRM中创建批量记录。有时,记录的数量会非常高

//Without Threading

foreach (EntityCollection col in RetrieveContactsFromStaticML(ConnectToCrm(),marketingListRecord))
{
  CreateRecordsAgainstContact(_orgService, col, rewardDetails, errorLoger);
}
但这需要花费太多的时间来执行。因为每次调用CreateRecordsAgainstContact方法时,进程都会等待该方法执行

所以我决定使用线程

//With Threading

foreach (EntityCollection col in RetrieveContactsFromStaticML(ConnectToCrm(),marketingListRecord))
{
    var t1 = Task.Factory.StartNew(delegate ()
{
    CreateRecordsAgainstContact(_orgService, col, rewardDetails,errorLoger);
});

}
但我不确定:这是使用线程的最佳方式吗

这是我的密码:

namespace ActivityDistribution
{

    public class Distribution : IDistribution
{
        private static IOrganizationService _orgService = null;
    private static Logger errorLoger = new Logger();

    public void CreateRewardsAndOfferRecords(Guid campaignActivityId)
    {
        RewardsAndOffers rewardDetails = new RewardsAndOffers();
        Entity CampaignActivity = null;
        Entity ParentCampaign = null;
        EntityCollection marketingListCollection = null;
        try
        {
            _orgService = ConnectToCrm();

            #region RewardsAndOffers Details
            CampaignActivity = _orgService.Retrieve("campaignactivity", campaignActivityId, new ColumnSet("subject", "regardingobjectid", "channeltypecode"));
            ParentCampaign = _orgService.Retrieve("campaign", new Guid(((EntityReference)CampaignActivity["regardingobjectid"]).Id.ToString()), new ColumnSet("name", "istemplate", "statuscode", "new_rewardcategory", "new_rewardsubcategory"));
            rewardDetails.CampaignActivity = new EntityReference(CampaignActivity.LogicalName, CampaignActivity.Id);
            rewardDetails.ParentCampaign = new EntityReference(ParentCampaign.LogicalName, ParentCampaign.Id);
            #endregion

            #region Get MarketingList of given Campaign Activity
            QueryExpression queryMarketingList = new QueryExpression("list")
            {
                ColumnSet = new ColumnSet("query", "listname", "type"),
                LinkEntities =
                {
                    new LinkEntity
                    {
                        JoinOperator = JoinOperator.Inner,
                        LinkFromAttributeName = "listid",
                        LinkFromEntityName = "list",
                        LinkToAttributeName = "itemid",
                        LinkToEntityName = "campaignactivityitem",
                        LinkEntities =
                        {
                            new LinkEntity
                            {
                                JoinOperator = JoinOperator.Inner,
                                LinkFromAttributeName = "campaignactivityid",
                                LinkFromEntityName = "campaignactivityitem",
                                LinkToAttributeName = "activityid",
                                LinkToEntityName = "campaignactivity",
                                LinkCriteria =
                                {
                                    Conditions =
                                    {
                                        new ConditionExpression("activityid", ConditionOperator.Equal,  rewardDetails.CampaignActivity.Id)
                                    }
                                }
                            }

                        },

                    }
                }
            };
            marketingListCollection = _orgService.RetrieveMultiple(queryMarketingList);
            #endregion

            #region Fetch MarketingList's Contacts and Create Rewards&Offers Redords against MarketingList's Contacts
            if (marketingListCollection.Entities.Count() > 0)
                foreach (var marketingListRecord in marketingListCollection.Entities)
                {
                    //With Threading
                    foreach (EntityCollection col in RetrieveContactsFromStaticML(ConnectToCrm(), marketingListRecord))
                    {
                        var t1 = Task.Factory.StartNew(delegate ()
                        {
                            CreateRecordsAgainstContact(_orgService, col, rewardDetails, errorLoger);
                        });
                    }
                    //Without Threading
                    foreach (EntityCollection col in RetrieveContactsFromStaticML(ConnectToCrm(), marketingListRecord))
                    {
                        CreateRecordsAgainstContact(_orgService, col, rewardDetails, errorLoger);
                    }
                }
            #endregion
        }
        catch (Exception ex)
        {
            errorLoger.Log(ex);
        }

    }
    private static IOrganizationService ConnectToCrm()
    {
        IOrganizationService orgService = null;
        ClientCredentials credentials = new ClientCredentials();
        credentials.UserName.UserName = Credentials.UserName;
        credentials.UserName.Password = Credentials.Password;
        Uri serviceUri = new Uri(Credentials.OrganizationService);
        OrganizationServiceProxy proxy = new OrganizationServiceProxy(serviceUri, null, credentials, null);
        proxy.EnableProxyTypes();
        proxy.Timeout = new TimeSpan(4, 0, 0);
        orgService = (IOrganizationService)proxy;
        return orgService;

    }
    public static IEnumerable<EntityCollection> RetrieveContactsFromStaticML(IOrganizationService service, Entity entity)
    {
        var queryExpression = new QueryExpression()
        {
            Distinct = false,
            EntityName = "contact",
            ColumnSet = new ColumnSet("fullname", "telephone1"),
            LinkEntities =
                {
                    new LinkEntity
                    {
                        JoinOperator = JoinOperator.Inner,
                        LinkFromAttributeName = "contactid",
                        LinkFromEntityName = "contact",
                        LinkToAttributeName = "entityid",
                        LinkToEntityName = "listmember",
                        LinkEntities =
                        {
                            new LinkEntity
                            {
                                JoinOperator = JoinOperator.Inner,
                                LinkFromAttributeName = "listid",
                                LinkFromEntityName = "listmember",
                                LinkToAttributeName = "listid",
                                LinkToEntityName = "list",
                                LinkCriteria =
                                {
                                    Conditions =
                                    {
                                        new ConditionExpression("listid", ConditionOperator.Equal, entity.Id)
                                    }
                                }
                            }
                        }

                    }
                }
        };

        foreach (EntityCollection col in RetrieveMultipleRecords(service, queryExpression))
        {
            yield return col;
        }
    }
    public static IEnumerable<EntityCollection> RetrieveMultipleRecords(IOrganizationService service, QueryExpression queryExpression)
    {
        int fetchCount = 5000;
        int pageNumber = 1;



        queryExpression.PageInfo = new PagingInfo();
        queryExpression.PageInfo.Count = fetchCount;
        queryExpression.PageInfo.PageNumber = pageNumber;
        queryExpression.PageInfo.PagingCookie = null;
        while (true)
        {
            EntityCollection col = new EntityCollection();
            EntityCollection collection = service.RetrieveMultiple(queryExpression);
            if (collection.Entities.Count > 0)
                foreach (Entity e in collection.Entities)
                {
                    col.Entities.Add(e);
                }
            queryExpression.PageInfo.PageNumber++;
            queryExpression.PageInfo.PagingCookie = collection.PagingCookie;

            yield return col;
            if (!collection.MoreRecords)
                yield break;
        }
    }
    public static void CreateRecordsAgainstContact(IOrganizationService service, EntityCollection contactColletion, RewardsAndOffers rewardsAndOffers, Logger errorLoggger)
    {
        var requestWithResults = new ExecuteMultipleRequest()
        {
            Settings = new ExecuteMultipleSettings()
            {
                ContinueOnError = true,
                ReturnResponses = false
            },
            Requests = new OrganizationRequestCollection()
        };

        int maxRecordExecuteCount = 0;
        int totalRecords = 0;
        foreach (Entity contact in contactColletion.Entities)
        {
            Entity entity = new Entity("new_rewardsandoffers");
            entity["new_campaignactivity"] = rewardsAndOffers.CampaignActivity;
            entity["new_campaign"] = rewardsAndOffers.ParentCampaign;
            entity["new_contact"] = new EntityReference("contact", contact.Id);
            CreateRequest createRequest = new CreateRequest { Target = entity };
            requestWithResults.Requests.Add(createRequest);
            maxRecordExecuteCount++;
            totalRecords++;
            if (maxRecordExecuteCount == 1000 || totalRecords == contactColletion.Entities.Count())
            {
                service.Execute(requestWithResults);
                maxRecordExecuteCount = 0;
                requestWithResults.Requests = new OrganizationRequestCollection();
            }
        }
    }
    }
 public class RewardsAndOffers
{
    public EntityReference ParentCampaign { get; set; }
    public EntityReference CampaignActivity { get; set; }
    public OptionSetValue RewardCategory { get; set; }
    public OptionSetValue RewardSubCategory { get; set; }
}
 class Credentials
{
    public static string OrganizationService
    {
        get
        {
            return ConfigurationManager.AppSettings["OrganizationService"].ToString();
        }
    }

    public static string UserName
    {
        get
        {
            return ConfigurationManager.AppSettings["UserName"].ToString();
        }
    }

    public static string Password
    {
        get
        {
            return ConfigurationManager.AppSettings["Password"].ToString();
        }
    }
}
}

我想使用手动创建的线程并控制它的计数。在此示例中,有一个由多个线程处理的公共队列:

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
        }
    }
}
ExecuteMultipleRequest用于批量操作,我建议将其签出并避免执行线程:

这是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);

完整样本在这里

这不起作用。并发执行的任务不能共享同一IOOrganizationService实例。您需要一个提供可重用服务实例的对象池。将池中的实例数限制为最多10个


我建议使用BlockingCollection的生产者-消费者模式来安排需要完成的工作。请参阅。

我会将循环移动到自己的线程中,并根据可能的执行速度,使for循环为每次迭代创建自己的线程。这将释放主线程来完成其他工作,而其他线程则完成它们的工作。@Ortund您能用示例代码解释一下吗?我不清楚你想在这里说什么@rahuldesai我无法发布答案,事实上,我本应该投票结束这个问题,因为它被搁置的确切原因,但我会这么做。。。这只会提供有限的吞吐量增益。如果正确编码,这种方法可以实现每小时约100万次在线操作,如果这还不够,则CRM不是完成此任务的正确工具。。。