parallel.invoke cancellation token - .net-4.0

When using Parallel.Invoke, you're able to pass in ParallelOptions which includes a cancelationToken. Is it possible to use that token in the invocations to determine if exiting should occur? Should a reference to the CancellationTokenSource be used from within the actions?
CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
Parallel.Invoke(po,
new Action(() => { if (cts.IsCancellationRequested) return; Console.WriteLine("Invoked Method 1"); }),
new Action(() => { if (cts.IsCancellationRequested) return; Console.WriteLine("Invoked Method 2"); }),
new Action(() => { if (cts.IsCancellationRequested) return; Console.WriteLine("Invoked Method 3"); cts.Cancel(); }),
new Action(() => { if (cts.IsCancellationRequested) return; Console.WriteLine("Invoked Method 4"); }),
new Action(() => { if (cts.IsCancellationRequested) return; Console.WriteLine("Invoked Method 5"); })
);
Update: The cancellation was happening too late. I was doing it outside of the invoked methods.
Note: If the cancellation happens soon enough, the Parallel.Invoke will throw, but otherwise the inoked methods will exit without fail.

Yes. For example:
CancellationToken ct = tokenSource.Token;
ParallelOptions po = new ParallelOptions { CancellationToken = ct; };
Parallel.Invoke(po
() => { Console.WriteLine(ct.IsCancellationRequested); },
// etc
);
In particular, you could pass the cancellation token into other methods which may propagate it to asynchronous tasks.

There is a fairly good example on msdn.
it seems you can both query the status and use the cancellationToken to signal the scheduler.
http://msdn.microsoft.com/en-us/library/dd997364.aspx

Related

NetCore3 API not returning/serializing my data

I have the following controller:
[HttpGet("idfull/{id}")]
public async Task<IActionResult> GetAccountByIdFull(int id)
{
try
{
var response = await _accountFacade.GetAccountByIdAsync(id, full: true).ConfigureAwait(false);
if (response == null)
return NoContent();
return Ok(response);
}
catch (KeyNotFoundException kEx)
{
return NotFound();
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
}
The Facade layer:
public async Task<AccountViewModel> GetAccountByIdAsync(int accountId, bool full = false)
{
try
{
var unmappedResponse = await _accountService.GetAccountByIdAsync(accountId, full);
var mappedResponse = _mapper.Map<AccountViewModel>(unmappedResponse);
return mappedResponse;
}
catch
{
throw;
}
}
The service layer:
public async Task<Account> GetAccountByIdAsync(int accountId, bool full = false)
{
try
{
Account account;
if (full)
{
account = await _repo.GetOneAsync<Account>(x => x.AccountId == accountId);
account.Company = await _repo.GetOneAsync<Company>(filter: x => x.CompanyId == account.CompanyId,
includes: source => source
.Include(c => c.CompanyTransferType)
.ThenInclude(ctt => ctt.PartnerCompanyAccountType)
.Include(c => c.CompanyTransferType).ThenInclude(ctt => ctt.TransferType)
.Include(c => c.CompanyEquipment).ThenInclude(ce => ce.Equipment)
.Include(c => c.CompanyAccountGroup)
.Include(c => c.CompanyAccountType));
account.AccountContact = await _repo.GetAsync<AccountContact>(filter: x => x.AccountId == accountId);
account.AccountEquipment = await _repo.GetAsync<AccountEquipment>(filter: x => x.AccountId == accountId,
includes: source => source
.Include(ae => ae.AccountEquipmentFee).Include(ae => ae.CompanyEquipment).ThenInclude(ce => ce.Equipment));
account.AccountPickVolumeDefaultAccount = await _repo.GetAsync<AccountPickVolumeDefault>(filter: x => x.AccountId == accountId,
includes: source => source
.Include(a => a.Equipment).Include(a => a.PartnerAccount));
}
else
{
account = await _repo.GetByIdAsync<Account>(accountId);
}
if (account == null)
throw new KeyNotFoundException($"Could not find Account with ID: {accountId}");
return account;
}
catch
{
throw;
}
}
What I do not understand is, the controller returns OK status and all of my fields are populated. However, the API hangs and does not return my data, in other words, the Swagger API (including front-end application) does not receive the response and keeps on showing the loading button.
I have a funny feeling it has something to do with Serialization, but not sure how to fix it.
I have made sure to turn off SelfRefenceLooping, as can be seen here:
services.AddControllers().AddNewtonsoftJson(setup =>
{
setup.SerializerSettings.ContractResolver = new DefaultContractResolver();
setup.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
Why is the API not returning the JSON object?
Can you try without the .ConfigureAwait(false)?
Except for that, you code seems ok and the API should work fine.
If you don't have it, I would recommend adding Swagger to your API, it's just a matter of 5-10 lines and it helps a lot in the development phase (and also avoid manual mistakes while testing). Here is the official documentation: ASP.NET Core web API help pages with Swagger / OpenAPI
You can also try to add a very dumb action in your controller, to try to identify where the issue comes from (Controller layer? Service layer? Facade layer?)

How to stop Promise.all loop when it rejects

I'm having a hard time trying to stop the loop in promise.all if one promise rejects it. Here's how I did it. Is there something wrong with this?
Promise.all(myArray.map((obj) => {
this.someFunction(obj);
}))
Here's the function I call..
someFunction(){
return new Promise(function (resolve, reject) {
....
reject()
})}
I have updated my code, it is tested and it works on my machine with the mock data I feed it with. I am not exactly sure how the rest of your code is structured but it is something likes this: Oh and you cannot break out of a map, but we will use a simple for loop because we can break out of that:
function someFunction(){
return new Promise(function (resolve, reject) {
// I will be rejeccting a boolean
// If you are resolving something, resolve it as true
reject(false)
})}
async function shouldStopLoop(){
// the boolean will come here
// if it is false, the catch block will return
// if it is true, the try block will return
let stopLoop = null;
let result = null;
try {
result = await someFunction();
return result
} catch(error) {
stopLoop = error;
return stopLoop;
}
}
function mayReturnPromiseAll() {
let myArray = ['stuf to loop over...']
let arraytoGoInPrimiseAll = [];
// Array.prototype.map cannot be stopped
// Thats why we will use a for loop and we will push the data we need
// into another array
for (var i = 0; i < myArray.length; i++) {
if (!this.someFunction(obj)) {
break;
} else {
// push things in arraytoGoInPrimiseAll
}
}
if(arraytoGoInPrimiseAll.length > 0){
return Promise.all(arraytoGoInPrimiseAll)
} else {
// do something else
}
};
Try this:
const arrayOfFunctions = myArray.map(obj => this.someFunction(obj))
Promise.all(arrayOfFunctions).then(values => {
console.log(values);
}).catch(error => {
console.log(error)
});

Get JavaScript Array of Objects to bind to .Net Core List of ViewModel

I have a JS Array of Objects which, at time of Post contains three variables per object:
ParticipantId,
Answer,
ScenarioId
During post, there is an Array the size of 8 (at current anyway) which all correctly contain data. When I call post request, the Controller does get hit as the breakpoint triggers, the issue is when I view the List<SurveyResponse> participantScenarios it is shown as having 0 values.
The thing I always struggle to understand is that magic communication and transform between JS and .Net so I am struggling to see where it is going wrong.
My JS Call:
postResponse: function () {
var data = JSON.stringify({ participantScenarios: this.scenarioResponses})
// POST /someUrl
this.$http.post('ScenariosVue/PostScenarioChoices', data).then(response => {
// success callback
}, response => {
// error callback
});
}
My .Net Core Controller
[HttpPost("PostScenarioChoices")]
public async Task<ActionResult> PostScenarioChoices(List<SurveyResponse> participantScenarios)
{
List<ParticipantScenarios> addParticipantScenarios = new List<ParticipantScenarios>();
foreach(var result in participantScenarios)
{
bool temp = false;
if(result.Answer == 1)
{
temp = true;
}
else if (result.Answer == 0)
{
temp = false;
}
else
{
return StatusCode(400);
}
addParticipantScenarios.Add(new ParticipantScenarios
{
ParticipantId = result.ParticipantId,
Answer = temp,
ScenarioId = result.ScenarioId
});
}
try
{
await _context.ParticipantScenarios.AddRangeAsync(addParticipantScenarios);
await _context.SaveChangesAsync();
return StatusCode(201);
}
catch
{
return StatusCode(400);
}
}

DB transaction with callback

I am trying to figure out how to correctly set this block of code up so that the commit function will wait until all of the rows are inserted. Currently I am reading a csv and need to insert a new row per column into a table. I also need to add a row into a parent table for that. I need all of that to finish before I call commit. I have yet to master callbacks so please be gentle.
db.beginTransaction(function (err) {
if (err)
{
//could not begin a transaction for some reason.
logger.error("beginTransaction error: " +err);
}
//need to wrap this *************
db.query("INSERT INTO TABLE VALUES ('" + unique_id + "','real_time','" + msg + "',1,1,LOCALTIMESTAMP)", function(err){
if(err)
{
logger.error("error insert into parent table: "+err);
}
});
for(var i = 0; i < headers.length; i++)
{
//replaces single quote (') with two single quotes to escape it ('')
values[i] = values[i].replace("'","''");
db.query("INSERT INTO TABLE VALUES ('" + unique_id + "','" + headers[i] + "',0,'" + values[i] + "')", function(err){
if(err)
{
logger.error("error insert into child table: "+err);
}
});
}
//To here ************
db.commitTransaction(function (err) {
if (err)
{
//error during commit
logger.error("Commit error: "+err);
}
}); //end of commitTransaction
callback();
});//End of beginTransaction
There's three basic ways of tackling this synchronization problem which I'll demonstrate here using new style arrow functions. The traditional Node way is with callbacks:
a((err, resultA) => {
// Fires when A is done or errored out
if (err) {
// Log, panic, etc.
return;
}
b((err, resultB) => {
// Fires when A and B are done or A is done and B errored out
if (err) {
// Log, panic, etc.
return;
}
c((err, resultC) => {
// Fires when A, B and C are done or A and B are done and C errored out
if (err) {
// Log, panic, etc.
return;
}
});
});
});
This is what people refer to as "callback hell" because the nesting and error propagation code gets more and more ridiculous as your dependencies grow in complexity. I find this style unsustainable for any non-trivial application.
The next style is Promise-driven:
a().then(resultA => {
// Fires when A is done
return b();
}).then(resultB => {
// Fires when B is done
return c();
}).then(resultC => {
// Fires when C is done
}).catch(err => {
// Fires if any of the previous calls produce an error
});
This tends to be a lot "flatter" and easier to follow, but it's still a lot of heavy syntax for what should be simple. The newer async/await style builds on promises by adding support for them to the JavaScript syntax:
try {
let resultA = await a();
let resultB = await a();
let resultC = await a();
} catch(err) {
// Fires when any error occurs
}
This works inside any function tagged async like:
async function runQueries() {
// async code
}
Which can make your life a lot easier. You can also use conventional try/catch notation for errors, they're propagated accordingly.
As tadman states, it's very important that you don't manually escape values and use parameterized queries instead. Make sure you fix this first.
Unfortunately it doesn't look like node-odbc supports promises. You may be able to get it to work with something like Bluebird.promisify. Currently what you want is to keep track of how many successful inserts were completed and then commit the transaction if they all complete successfully.
let successfulInsertions = 0;
let insertionAttempts = 0;
for(var i = 0; i < headers.length; i++) {
db.query("INSERT INTO TABLE VALUES (?, ?, ?, ?)", params, err => {
if (err) {
logger.error("error insert into child table: "+err);
}
else {
successfulInsertions++;
}
insertionAttempts++;
if (insertionAttempts === headers.length) {
if (successfulInsertions === insertionAttempts) {
db.commitTransaction();
}
else {
db.rollbackTransaction();
}
callback();
}
});
}
There are libraries out there that will help with this but they would require rewriting your code a bit. If you can use Bluebird's promisifyAll on the node-odbc library I would rewrite it using async/await (this is still asynchronous and functions the same):
await db.beginTransactionAsync();
try {
await db.queryAsync("INSERT INTO TABLE VALUES (?, ?, ?, ?)", params);
await Promise.all(headers.map((header, i) =>
db.queryAsync("INSERT INTO TABLE VALUES (?, ?, ?, ?)", [unique_id, header, 0, values[i])
);
await db.commitTransactionAsync();
} catch (err) {
logger.error(err);
db.rollbackTransaction();
}
Note that if beginTransaction throws an error for some reason this code will throw an error.
I don't really understand your code, why don't you return or stop your code if there is an error?
Here for example, you should have your code like this
db.beginTransaction(function (err) {
if (err)
return logger.error("beginTransaction error: " +err), db.rollback(/*...*/)
//....
}
Second, you should change your whole code with the async/await syntax.
async function foo () {
await new Promise((next, err)=> {
db.beginTransaction(e => e ? err(e) : next())
})
await new Promise((next, err)=> {
db.query(`INSERT INTO TABLE VALUES ('${unique_id}','real_time','${msg}',1,1,LOCALTIMESTAMP)`, e => e ? err(e) : next())
})
for (var i = 0; i < headers.length; i++) {
await new Promise((next, err)=> {
db.query(`INSERT INTO TABLE VALUES ('${unique_id}','${headers[i]}',0,'${values[i]}')`, e => e ? err(e) : next())
})
}
await new Promise((next, err)=> {
db.commitTransaction(e => e ? err(e) : next())
})
}
foo()
.then(()=> callback())
.catch(e=> logger.error(`Error: ${e}`))

Alternative to Application.DoEvents in console application to make Forms.WebBrowser load javascripts

I'm using System.Windows.Forms.WebBrowser in console application to render a web page then invoke scripts on it. To render the web page, I use Application.DoEvents to load and execute scripts.
However sometime the app hangs on calling Application.DoEvents. I found no reason. I don't think I'm creating deadlock on the event loop.
Many people on the web says that one should not use Application.DoEvents at all because it creates more problems than it solves. So I'm thinking there must be an alternative to it. But I've searched a lot and find no alternative to Application.DoEvents.
Does anyone know one?
Any information is appreciated. Thank you in advance!
Thanks to Noseratio's help, I finished drafting my code but still there's freezing issue.
Take following code as example(code is too long so I pasted it on pastebin): http://pastebin.com/DkDcrirU
When you run this code, occasionally there will be at least one window fail to close. And if you attach to the frozen process, you will find the code stuck at following line(indicated by ">>>"):
public static bool NavigateLoadAndRender(WebBrowserContext browserContext, string url, TimeSpan loadTimeout, TimeSpan renderTime, out string errMsg)
{
ForceInitActiveXInstance(browserContext);
object axi = null;
Func<Uri> getBrowserUri = null;
Action<Uri> navigateBrowser = null;
Func<IHTMLDocument2> getBrowserDoc = null;
switch (browserContext.WebBrowserType)
{
case WebBrowserTypeEnum.Forms:
{
var browser = browserContext.GetWebBrowserAsFormsType();
getBrowserUri = () => browser.Url;
navigateBrowser = u =>
{
var finished = false;
browserContext.SyncContext.Post(state =>
{
browser.Navigate(u);
finished = true;
}, null);
while (!finished) Thread.Sleep(DefaultConfig_SyncContextPostCheckInterval);
};
getBrowserDoc = () =>
{
IHTMLDocument2 doc = null;
bool finished = false;
browserContext.SyncContext.Post(state =>
{
doc = (IHTMLDocument2)browser.Document.DomDocument;
finished = true;
}, null);
>>> while (!finished) Thread.Sleep(DefaultConfig_SyncContextPostCheckInterval);
return doc;
};
axi = GetActiveXInstance(browserContext);
}
break;
case WebBrowserTypeEnum.Wpf:
{
var browser = browserContext.GetWebBrowserAsWpfType();
axi = GetActiveXInstance(browser);
getBrowserUri = () => browser.Source;
navigateBrowser = u =>
{
var finished = false;
browserContext.SyncContext.Post(state =>
{
browser.Navigate(u);
finished = true;
}, null);
while (!finished) Thread.Sleep(DefaultConfig_SyncContextPostCheckInterval);
};
getBrowserDoc = () =>
{
IHTMLDocument2 doc = null;
bool finished = false;
browserContext.SyncContext.Post(state =>
{
doc = (IHTMLDocument2)browser.Document;
finished = true;
}, null);
while (!finished) Thread.Sleep(DefaultConfig_SyncContextPostCheckInterval);
return doc;
};
axi = GetActiveXInstance(browserContext);
}
break;
default: throw new ArgumentException("unknown browser type", browserContext.WebBrowserType.ToString());
}
var success = NavigateLoadAndRender(
axi, url,
getBrowserUri,
navigateBrowser,
//() => DoEvents(browser),
getBrowserDoc,
loadTimeout, renderTime, out errMsg);
return success;
}
Anyone knows what's happening?