我正在开发一个与Dynamics 365和Dynamics SDK集成的网站。我们在日志中看到了错误,例如“无法访问已处置的对象”。经过进一步调查,我们发现SDK方法不是线程安全的,因此需要重构代码以将其考虑在内。
我们有一个如下的方法,可以创建或更新Contact实体,具体取决于它是否已经存在:
public Guid? SetProfile(IProfile profile)
{
using (var xrm = new XrmServiceContext(_organizationService))
{
//check whether account already exists
var crmProfile = GetContact(xrm, profile.UserId);
if (crmProfile == null)
{
//create new account if required
{
crmProfile = new Contact
{
EMailAddress1 = profile.Username,
//lots of properties hidden to make for easier code example
};
}
xrm.AddObject(crmProfile);
}
else
{
//update existing account
crmProfile.new_Title = profile.Title.HasValue ? new OptionSetValue(profile.Title.Value) : null;
//lots of properties hidden to make for easier code example
xrm.UpdateObject(crmProfile);
}
var response = xrm.SaveChanges();
return crmProfile.Id;
}
}
当此方法由2个或更多用户同时执行时,错误"无法访问已处置的对象"将抛出,引用XrmServiceContext对象。
因此我知道我需要使这个方法是线程安全的,但它也需要是同步的,因为我们的UI依赖于具有方法的返回值。我玩了不同的线程方法:
然而,使用这两种方法我都无法让方法同步执行,所以我最终得到了:
public Guid? SetProfile(IProfile profile)
{
var task = new Task<Guid?>(() =>
{
using (var xrm = new XrmServiceContext(_organizationService))
{
//check whether account already exists
var crmProfile = GetContact(xrm, profile.UserId);
if (crmProfile == null)
{
//create new account if required
{
crmProfile = new Contact
{
EMailAddress1 = profile.Username,
//lots of properties hidden to make for easier code example
};
}
xrm.AddObject(crmProfile);
}
else
{
//update existing account
crmProfile.new_Title = profile.Title.HasValue ? new OptionSetValue(profile.Title.Value) : null;
//lots of properties hidden to make for easier code example
xrm.UpdateObject(crmProfile);
}
var response = xrm.SaveChanges();
return crmProfile.Id;
}
});
task.RunSynchronously();
return task.Result;
}
我在网上看到的所有东西都建议我应该使用StartNew方法,但这是针对我不能允许的异步调用,而且它似乎也不能保证一个新的线程 - 从我读过的内容我知道它很聪明,知道何时需要创建一个新线程 - 但在我的实例中,我必须确定一个新线程用于调用Dynamics。
问题:
非常感谢您提前的时间
亲切的问候
dotdev