Details
-
Task
-
Resolution: Works as Designed
-
Major - P3
-
None
-
2.5
-
Windows
Description
I cannot find a proper way to cancel a change stream watcher.
In the following example I can stop watching when I dispose the enumerator, but the exception is not correct in my opinion.
Instead of disposing the enumerator, I would like to run something like cursor.Cancel() to stop watching for changes and close the change stream. And It could throw an OperationCanceledException.
var cts = new CancellationTokenSource(5000); |
var client = new MongoClient("mongodb://localhost"); |
var db = client.GetDatabase("test"); |
var collection = db.GetCollection<BsonDocument>("test"); |
|
|
Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Start watching..."); |
|
|
var cursor = collection.Watch(); |
var enumerator = cursor.ToEnumerable().GetEnumerator(); |
|
|
|
|
cts.Token.Register(() =>
|
{
|
Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Cancellation token was cancelled."); |
enumerator.Dispose();
|
});
|
|
|
try
|
{
|
while (enumerator.MoveNext()) |
{
|
Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Received a change from database."); |
}
|
}
|
catch (Exception e) |
{
|
Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Exception: {e.Message}"); |
}
|
|
|
Console.WriteLine("Done"); |
Console output:
Console output:
|
10:50:55 - Start watching...
|
10:50:59 - Cancellation token was cancelled.
|
10:50:59 - Exception: Cannot access a disposed object.
|
Object name: 'MongoDB.Driver.Core.Bindings.CoreSessionHandle'.
|
In the following example I get the correct exception, but the MoveNext method returns true every second and I have to check if the cursor has any document.
var cts = new CancellationTokenSource(5000); |
var client = new MongoClient("mongodb://localhost"); |
var db = client.GetDatabase("test"); |
var collection = db.GetCollection<BsonDocument>("test"); |
|
|
Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Start watching..."); |
|
|
var cursor = collection.Watch(); |
|
|
try
|
{
|
while (cursor.MoveNext(cts.Token)) |
{
|
if(cursor.Current.Count()>0) |
Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Received {cursor.Current.Count()} changes from database."); |
else |
Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Nothing changed in database."); |
}
|
}
|
catch (Exception e) |
{
|
Console.WriteLine($"{DateTime.Now.ToLongTimeString()} - Exception: {e.Message}"); |
}
|
|
|
Console.WriteLine("Done"); |
Console output:
11:15:26 - Start watching...
|
11:15:26 - Nothing changed in database.
|
11:15:27 - Nothing changed in database.
|
11:15:28 - Nothing changed in database.
|
11:15:29 - Nothing changed in database.
|
11:15:30 - Exception: The operation was canceled.
|
Done
|
Here is an example how to cancel a file download using the .net WebClient. The same pattern could fit the cancellation of a change stream watcher.
var cts = new CancellationTokenSource(5000); |
var wc = new WebClient(); |
IWebProxy defaultWebProxy = WebRequest.DefaultWebProxy;
|
defaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
|
wc.Proxy = defaultWebProxy;
|
cts.Token.Register(() =>
|
{
|
Console.WriteLine("Cancel!"); |
wc.CancelAsync();
|
|
|
});
|
Console.WriteLine("Downloading..."); |
try
|
{
|
wc.DownloadFile(new Uri("http://downloads.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-4.0.2.zip"), @"c:\temp\mongodb.zip"); |
}
|
catch (Exception e) |
{
|
Console.WriteLine("Downloading was cancelled"); |
}
|