I need to run multiple web requests and measure time between request and corresponding response.
Both solutions with existing code using BackgroundWorker and new code using TPL library have following issue I cannot understand:
var watch = Stopwatch.StartNew();
queue.Enqueue(Task.Factory
.FromAsync<WebResponse>(webRequest.BeginGetResponse, webRequest.EndGetResponse, null)
.ContinueWith(task =>
{
using (var response = (HttpWebResponse)task.Result)
{
// Stopwatch shows wrong results
// After multiple request watch.Elapsed time arrives 10 seconds
// This is wrong be
// The same code running in Console Application works corectly
Debug.WriteLine("{0}\t{1}\t{2}", response.StatusCode, response.ContentType, watch.Elapsed);
// This lines are only in production WiForms app
if (EventWebRequestFinished != null)
{
// Update WinForm GUI elements (add to listboc)
}
}
},
The same issue I have also using DateTime.Now method.
If it's all code, without any static variables and etc., the cause of the problem may be closure of a variable 'watch'. Expression gets first value of variable and all next times uses only this value.
Try to send variable value via 3rd parameter 'state' of the FromAsync method.
Related
I am trying to consume a max of 1000 messages from kafka at a time. (I am doing this because i need to batch insert into MSSQL.) I was under the impression that kafka keeps an internal queue which fetches messages from the brokers and when i use the consumer.consume() method it just checks if there are any messages in the internal queue and returns if it finds something. otherwise it just blocks until the internal queue is updated or until timeout.
I tried to use the solution suggested here: https://github.com/confluentinc/confluent-kafka-dotnet/issues/1164#issuecomment-610308425
but when i specify TimeSpan.Zero (or any other timespan up to 1000ms) the consumer never consumes any messages. but if i remove the timeout it does consume messages but then i am unable to exit the loop if there are no more messages left to be read.
I also saw an other question on stackoverflow which suggested to read the offset of the last message sent to kafka and then read messages until i reach that offset and then break from the loop. but currently i only have one consumer and 6 partitions for a topic. I haven't tried it yet but i think managing offsets for each of the partition might make the code messy.
Can someone please tell me what to do?
static List<RealTime> getBatch()
{
var config = new ConsumerConfig
{
BootstrapServers = ConfigurationManager.AppSettings["BootstrapServers"],
GroupId = ConfigurationManager.AppSettings["ConsumerGroupID"],
AutoOffsetReset = AutoOffsetReset.Earliest,
};
List<RealTime> results = new List<RealTime>();
List<string> malformedJson = new List<string>();
using (var consumer = new ConsumerBuilder<Ignore, string>(config).Build())
{
consumer.Subscribe("RealTimeTopic");
int count = 0;
while (count < batchSize)
{
var consumerResult = consumer.Consume(1000);
if (consumerResult?.Message is null)
{
break;
}
Console.WriteLine("read");
try
{
RealTime item = JsonSerializer.Deserialize<RealTime>(consumerResult.Message.Value);
results.Add(item);
count += 1;
}
catch(Exception e)
{
Console.WriteLine("malformed");
malformedJson.Add(consumerResult.Message.Value);
}
}
consumer.Close();
};
Console.WriteLine(malformedJson.Count);
return results;
}
I found a workaround.
For some reason the consumer first needs to be called without a timeout. That means it will wait for a message until it gets at least one. after that using consume with timeout zero fetches all the rest of the messages one by one from the internal queue. this seems to work out for the best.
I had a similar problem, updating the Confluent.Kafka and lidrdkafka libraries from version 1.8.2 to 2.0.2 helped
The following example code successfully performs a callback to the Google App Script:
var SCRIPT_ID = "1eC5VsM2vkJXa9slM40MTKTlfARGAGyK1myMCU3AB_-Ox_jGxQaoPM8P2";
function getURL() { return getCallbackURL('testCallback'); }
function getCallbackURL(callback) {
var state = ScriptApp.newStateToken().withTimeout(3600).withMethod(callback).createToken();
return 'https://script.google.com/macros/d/'+SCRIPT_ID+'/usercallback?state='+state;
}
function doGet(e){ return HtmlService.createTemplate(" <div><p><a href='<?=getURL()?>' id='start-auth'><?=getURL()?></a></p></div>").evaluate()); }
function testCallback(e){
Logger.log('myVariable1= ' + e.parameter.myVariable1); // this doesn't work
Logger.log('myVariable2= ' + e.parameter.myVariable2); // this doesn't work
return HtmlService.createHtmlOutput('<b>Success. You can close this window. !</b>')
}
However I need to return a variable to the "testCallback" method as part of a HttpRepsonse redirect. I've tried settings a cookie and also setting a header variable in my asp.net C# application as follow:
HttpCookie cookie = new HttpCookie("myVariable1");
cookie.Value = "someValue1";
cookie.Expires = DateTime.Now.AddMinutes(1);
Response.Cookies.Add(cookie);
Response.AddHeader("myVariable2", "someValue2");
Response.Redirect(applicationCallbackUri, true);
but it's not clear whether the header or cookie variables are available to Google's callback method:
function testCallback(e){
Logger.log('myVariable1= ' + e.parameter.myVariable1);
Logger.log('myVariable2= ' + e.parameter.myVariable2);
return HtmlService.createHtmlOutput('<b>Success. You can close this window.
!</b>')
}
I've also tried using the .WithArguments method when creating the a new state token, but I'm not sure if its possible for my asp.net application to update the state object's arguments as part of the redirect/return.
I've also tried appending the variable to the Google Callback URL, e.g.
https://script.google.com/macros/d/1eC5VsM2vkJXa9slM40MTKTlfARGAGyK1myMCU3AB_-Ox_jGxQaoPM8P2?state=ADEpC8w0dL6mBVmDQHX3XcYcBP0JqQ5_etc&myVariable1=someValue1
However Google throws an "invalid state" error
The event object passed to your testCallback(e) function cannot reference HTTP headers or cookies and appending arbitrary url variables to the redirect url won't work either (the authorization server that does the redirect will omit them to ensure security).
The only valid way to send state vars is using the withArguments() method. However, your Logger.log() calls won't work b/c the calls (to the testCallback(e) function) are asynchronous and they are not tracked in the editor. Instead, try enabling StackDriver Logging from the Apps Script Editor's View menu and replace those Logger.log() calls with console.log(). Your logs should then show up under StackDriver Logging in your Google API Console for the project.
I am trying to understand how to write a WWW call in Unity. According to the description here http://docs.unity3d.com/ScriptReference/WWW.html I can inspect the isDone property, but in the example on the same page, it makes no attempt to inspect isDone.
The question I have is, if I make a WWW call and it takes several seconds to reply, doesn't the game freeze?
I would like to think the right code is this, but is it?
StartCoroutine(WaitForResponse(myWWWObject));
private IEnumerator WaitForResponse(WWW aRequest ) {
while ( ! aRequest.isDone )
yield return aRequest;
}
Does the game freeze until aRequest is done? Or is it truly asynchronous?
You need to understand Coroutines - a fundamental feature of Unity that allows you to write long-duration code functions (eg: longer then a frame) that will not freeze your game.
http://docs.unity3d.com/Manual/Coroutines.html
In C# you can spot a coroutine function because it has a return type of IEnumerator. And you can spot the locations in the code where the function will suspend and continue from again by the C# keyword yield.
Each MonoBehaviour class can manage coroutines, and if you tell it to start one with StartCoroutine(), then MonoBehaviour will call the coroutine every frame (sometimes more then once) until the Coroutine reaches the end.
For WWW class (which supports co-routines), all you need is to call this:
WWW www = new WWW(url);
yield return www;
You create a WWW class with the URL to retrievve, and the yield will basically be called each frame automatically by the MonoDevelop coroutine manager until www object says it has completed (successfully or failure).
Your game will not freeze at all during this time.
In the linked documentation page for WWW, the following method is a coroutine method:
IEnumerator Start() {
WWW www = new WWW(url);
yield return www;
Renderer renderer = GetComponent<Renderer>();
renderer.material.mainTexture = www.texture;
}
The yield statement is used to pause execution and return control to Unity and then to resume execution in the next game frame. For example yield return null; will cause execution to resume in the next frame. Additionally, you can extend that behaviour by using one of the classes that derive from YieldInstruction class, for example WaitForSeconds.
Consider yield return new WaitForSeconds(1f); - this will resume execution after 1 second of game time has passed. The WWW class works in similar way. You can use an instance of that class to yield execution, returning only after the download has been completed, no need to manually poll the isDone property.
Keep in mind that you can only yield in Coroutines, I advise you read up on them. If you want to do a WWW request not in a Coroutine then you have to poll the isDone manually and proceed when completed.
To answer last question: Will the game freeze when creating an instance of the WWW class? - No. The class works asynchronously. You can use it in normal Update/Start etc. functions and inside Coroutines with yield.
if I make a WWW call and it takes several seconds to reply, doesn't the game freeze?
Not, Game Will not be freez try this code and you will see that log "after corou" will show immediately even the picture is downloading.
public class WWWDemo : MonoBehaviour {
bool b = true;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update()
{
if (b) {
StartCoroutine(ExampleCoroutine());
Debug.LogWarning("after corou");
}
}
IEnumerator ExampleCoroutine()
{
b = false;
Debug.Log("Time : " + DateTime.Now);
string url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg";
WWW www = new WWW(url);
yield return www;
Debug.Log("Time : " + DateTime.Now);
Renderer render = gameObject.GetComponent<Renderer>();
render.material.mainTexture = www.texture;
Debug.Log("Time : " + DateTime.Now);
}
}
but the execution of next line will definitely stop after yield return www statement it will wait unitl the picture download while the rest events of Unity will execute async.
Consider below example as well separately. Start Event executes ones it will wait but update will run continuously.
IEnumerator Start() {
Debug.Log("Time : " + DateTime.Now);
string url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg";
WWW www = new WWW(url);
yield return www;
Debug.Log("Time : " + DateTime.Now);
Renderer render = gameObject.GetComponent<Renderer>();
render.material.mainTexture = www.texture;
Debug.Log("Time : " + DateTime.Now);
}
void Update()
{
Debug.Log("update is running while start is waiting for downloading");
}
I have been working on a WCF web service, which is used by a mobile app that would send some data to it and save to DB.
One of the test case is that we try to append 2 (or more) records in the app, and the service is called to do a batch insert / update action.
Everything goes fine when I test using localhost, but when we test it using production server, only
the first record is saved, while the other record triggers the error message
Unable to determine a valid ordering for dependent operations...store-generated values.
I have no idea what is the cause and how to solve it. I have done some research and I am quite sure that the related model/DB table has NO circular dependency or self dependency.
Below is a snippet of the web service:
public void submit(List<SubmissionParameter> param){
using (var context = ObjectContextManager.AuditEnabledInstance){
foreach (var item in param){
ReadingSubmission readingSubmission = context.ReadingSubmissions.Where(p => p.ReadingSubmissionUniqueIdentifier == item.Readingsubmissionuniqueidentifier).SingleOrDefault();
if (readingSubmission == null){
readingSubmission = new ReadingSubmission();
context.ReadingSubmissions.AddObject(readingSubmission);
}
readingSubmission.ReadingSubmissionUniqueIdentifier = item.Readingsubmissionuniqueidentifier;
readingSubmission.SystemID = item.Systemid;
readingSubmission.UserID = item.Userid;
foreach (var record in item.Readings){
SystemReading systemReading = context.SystemReadings.Where(p => p.SystemReadingUniqueIdentifier == record.Systemreadinguniqueidentifier).SingleOrDefault();
if (systemReading == null){
systemReading = new SystemReading();
readingSubmission.SystemReadings.Add(systemReading);
}
systemReading.SystemReadingUniqueIdentifier = record.Systemreadinguniqueidentifier;
systemReading.MeasurementID = record.Measurementid;
}
context.SaveChanges();
}
}
}
ReadingSubmission and SystemReading is a 1 to many relation
SubmissionParameter is just a transmission object as the mobile client will send the JSON object to this web service.
I use Telerik Fiddler to post the JSON into this web service for testing, so I am quite sure the problem is not at the mobile client side.
Any help is appreciated! Thanks!
Finally I solve the problem though I am not quite sure why it works.
I move the context.SaveChanges() out of the foreach loop then it all works again for
both localhost and production
Hope it can help someone to save some time
I don't know much about Flash but we are working on a site that has a flash form and when the users pick an option, like selecting a value from a drop down list, we need the value to be passed to asp.net server-side code. What's the easiest way to do this?
Flash can invoke server side service. So use GET or POST to pass data
You could explore these options:
1) Communicate between the SWF and the containing page through JavaScript
2) Communicate via asp.net webservices from the SWF directly to the webservice.
3) Not sure but could probably do a POST to a processing aspx page?
HTH
I think a good option is to use the XML class so consider this:
var xmlRequest = new XML();
xmlRequest.onLoad = parseXMLResponse;
xmlRequest.load("http://yourpathtoyourserver/file.aspx?listselectedvalue=something");
function parseXMLRequest(loaded)
{
trace("hi");
}
You can also have the page give you data back this way so it's not just one way communication.
Assuming you are using Action Script 2.
Read the important notes at the bottom of each codes pertain to sending and retrieving data from flash to .net page. Explanation of the code is in the comment inside the code.
Flash Part (Action Script 2)
//function to send collected form data to asp.net page
//use other control/button to call this function
//important: in order for the 'onLoad' event to work correctly, this function has to be 'Void'
function sendForm():Void
{
//create LoadVars object
var lv_in:LoadVars = new LoadVars();
var lv_out:LoadVars = new LoadVars();
//set onLoad event
lv_in.onLoad = function(success:Boolean)
{
//if success, meaning data has received from .net page, run this code
if (success)
{
//lv_in.status is use to get the posted data from .Net page
statusMsg.text = "Thank you for filling up the form!" + lv_in.status;
}
//if fail, run this code
else
{
statusMsg.text = "The form you are trying to fill up has an error!";
}
}
//this is the collected data from the form
lv_out.userName = txtUserName.text;
lv_out.userAddress = txtUserAddress.text;
lv_out.userBirthday = txtUserBirthday.text;
//begin invoke .net page
lv_out.sendAndLoad("ProcessDataForm.aspx", lv_in, "POST");
}
Important note:
The function that contain onLoad event, in this case sendForm function, has to be Void function, meaning it's not returning value. If this function return value, what happen is the function will be executed all the way without waiting for the returned data from .net page, thus the onLoad event will not be set properly.
.Net Part
public void ProcessData
{
//process the data here
Response.Write("status=processed&");
}
Important note:
To send data/message back to flash, you can use Response.Write. However, if you want Action Script to parse the posted message/data from .Net page keep in mind you have to include & symbol at the end of the message. When parsing data/message, Action Script will stop at & symbol, thus leave the rest of the message alone and only get the message under sent variable.