c# - Not every result of IProgress<int> comes out of the task -
consider following implementation, method accepts iprogress<int>, iterates on 10000 objects. numbers array variable returns 10000 objects, iprogress<int> reports between 9970 - 9980 objects. varies per run, "lost".
    protected async override task<int[]> collectdataasyncimpl(iprogress<int> progress) {                         return await task.run<int[]>(() => {              var numbers = new list<int>();              foreach (var idx in new int32range(1, 10000).asenumerable().index()) {                                                              numbers.add(idx.value);                                      if (progress != null) {                     progress.report(idx.value);                 }              }              return numbers.toarray();         });     } as reference, here's test ran. fails @ third assert assert.equal(10000, result[9999]);.
[fact] async void reportsprogress() {                 var sut = new integercollector();     var result = new list<int>();     var output = await sut.collectdataasync(new progress<int>(i => result.add(i)));     assert.equal(10000, output.length);     assert.equal(1, result[0]);     assert.equal(10000, result[9999]); } clearly i'm doing wrong, or don't understand internals of task/threading. implementation of iprogress<int> new progress<int>(i => result.add(i)) not correct? should make thread safe, , if so, how do that?
github has code can clone & test if need be: https://github.com/kodefoxx/kf.datacollection/tree/master/source/kf.datacollection
it because of how progress<t> implemented. when created, progress<t> captures synchronization context , uses execute i => result.add(i). since running test, assume there no synchronization context. in case progress<t> uses default synchronizationcontext, posts work items thread pool (threadpool.queueuserworkitem). task completes before thread pool processes queued items, , explains results inconsistency.
a simple way check if case: change iprogress<int> argument action<int> , pass i => result.add(i) delegate directly, without wrapping progress<t>.
Comments
Post a Comment