我在EWS中运行多个用户模拟时遇到问题,当我想收到每个模拟人员日历(可能有100人)的通知时。
目前我有一个Outlook帐户,他有权模仿所有其他用户,并且所有ExchangeService对象都获得此帐户凭据
简短版本是,当我尝试通过唯一ID绑定到约会时,只要我只有一个线程在运行,它就可以工作。当我开始一个包含新的Exchange服务的新线程及其自己的订阅时,我不会在Appointment.Bind()上收到任何响应 - 请求。
当我运行我的程序的两个实例时,每个程序只有一个线程,它工作正常,但是一旦我用新的ExchangeService启动一个新线程,Appointment.Bind()就不会给出任何响应。
关于这一点的奇怪部分是,它在两周前工作正常,但突然它停止工作,我没有改变我的代码。
我已经创建了一个关于我的问题的快速演示:
class Program
{
static void Main(string[] args)
{
var x = new OutlookListener("user1@server.com");
var y = new OutlookListener("user2@server.com");
new Thread(x.Start).Start();
new Thread(y.Start).Start();
while (true)
{
}
}
}
class OutlookListener
{
private ExchangeService _ExchangeService;
private AutoResetEvent _Signal;
public OutlookListener(string emailToImp)
{
_ExchangeService = new ExchangeService(ExchangeVersion.Exchange2010_SP1)
{
Credentials = new NetworkCredential("superuser@server.com", "password"),
Url = new Uri("exchangeUrl"),
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, emailToImp)
};
}
public void Start()
{
var subscription = _ExchangeService.SubscribeToStreamingNotifications(new FolderId[] { WellKnownFolderName.Calendar },
EventType.Created);
var connection = CreateStreamingSubscription(_ExchangeService, subscription);
Console.Out.WriteLine("Subscription created.");
_Signal = new AutoResetEvent(false);
_Signal.WaitOne();
subscription.Unsubscribe();
connection.Close();
}
private StreamingSubscriptionConnection CreateStreamingSubscription(ExchangeService service, StreamingSubscription subscription)
{
var connection = new StreamingSubscriptionConnection(service, 30);
connection.AddSubscription(subscription);
connection.OnNotificationEvent += OnNotificationEvent;
connection.OnSubscriptionError += OnSubscriptionError;
connection.OnDisconnect += OnDisconnect;
connection.Open();
return connection;
}
private void OnNotificationEvent(object sender, NotificationEventArgs args)
{
// Extract the item ids for all NewMail Events in the list.
var newMails = from e in args.Events.OfType<ItemEvent>()
where e.EventType == EventType.Created
select e.ItemId;
foreach (var newMail in newMails)
{
var appointment= Appointment.Bind(_ExchangeService, newMail); //This is where I dont get a response!
Console.WriteLine(appointment.Subject);
}
}
private void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
{
}
private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
}
}
有什么建议吗?
答案 0 :(得分:2)
我遇到了同样的问题,发现我的EWS解决方案受到两个因素的限制。 默认情况下,System.Net.ServicePointManager.DefaultConnectionLimit设置为2,我已将其更改为20,以便与Exchange Online的限制策略相匹配。
其次,ExchangeService对象上的ConnectionGroupName属性可用于将连接池连接到具有与DefaultConnectionLimit属性的并发连接cohernet限制的不同相关组。
覆盖设置的一种方法是将ConnectionGroupName属性设置为您创建的每个ExchangeService对象的唯一值。
ExchangeService exchangeService = new ExchangeService()
{
ConnectionGroupName = Guid.NewGuid().ToString()
};
答案 1 :(得分:1)
为什么需要多个线程?
在我的情况下,我已根据smtpaddress为我想要模拟的每封电子邮件创建了一个服务字典,我订阅了所有这些服务。所有这些都可以在一个线程中发生,任何用户的所有通知都将在OnNotificationEvent中处理。 [这个代码只是为了显示逻辑,而不是完整的编译和运行]
var service = new ExchangeService(exchangeVersion);
var serviceCred = ((System.Net.NetworkCredential)(((WebCredentials)(Services.First().Value.Credentials)).Credentials));
service.Credentials = new WebCredentials(serviceCred.UserName, serviceCred.Password);
service.AutodiscoverUrl(userSmtp, RedirectionUrlValidationCallback);
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userSmtp);
Services.Add(userSmtp, service);
请注意,Services.First()。Value是可以模拟所有其他用户的服务,此处它被克隆为用户的编号。
之后所有服务的订阅(请注意,现在每个服务都冒充不同的用户)
foreach (var service in Services.Values)
{
SubscribeToService(service);
}
以及SubscribeToService的定义如下
private void SubscribeToService(ExchangeService service)
{
if (service.ImpersonatedUserId == null)
return;
if (service.Url == null)
return;
var serviceName = service.ImpersonatedUserId.Id;
var streamingSubscription =
service.SubscribeToStreamingNotifications(new FolderId[] { WellKnownFolderName.DeletedItems, WellKnownFolderName.Calendar },
EventType.FreeBusyChanged, EventType.Moved, EventType.Created, EventType.Modified);
if (!Connections.ContainsKey(service.Url))
{
Connections.Add(service.Url, new StreamingSubscriptionConnection(service, 30));
}
var connection = Connections[service.Url];
CloseConnection(connection);
if (!_subscriptions.ContainsKey(serviceName))
{
_subscriptions.Add(serviceName, streamingSubscription);
connection.AddSubscription(streamingSubscription);
}
}
}
所有这一切都可以在一个单独的线程中发生,我希望我的回答能够帮到你 干杯