This question already has an answer here:
How to put Json inside asynctask - Android
(1 answer)
Closed 9 years ago.
I have an Asynctask that uses a Json function in the doInBackground part. The function collects an array of comments and places them into a variable called KEY_COMMENTS. In the onPreExecute it places the comments into a textView using a for loop to select each comment individually. The problem is that its not selecting each comment it will only select one. If I set the loop to go for more than 1 time it will crash the app. Here is my code,
class loadComments extends AsyncTask<JSONObject, String, JSONObject> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
protected JSONObject doInBackground(JSONObject... params) {
//do your work here
JSONObject json2 = CollectComments.collectComments(usernameforcomments, offsetNumber);
return json2;
}
#Override
protected void onPostExecute(JSONObject json2) {
try {
if (json2.getString(KEY_SUCCESS) != null) {
registerErrorMsg.setText("");
String res2 = json2.getString(KEY_SUCCESS);
if(Integer.parseInt(res2) == 1){
JSONArray array = json2.getJSONArray(KEY_COMMENT);
for(int i = 0; i < 2; i++) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
commentBox.setBackgroundResource(R.drawable.comment_box_bg);
layoutParams.setMargins(0, 10, 0, 10);
commentBox.setPadding(0,0,0,10);
commentBox.setOrientation(LinearLayout.VERTICAL);
linear.addView(commentBox, layoutParams);
commentBoxHeader.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
commentBoxHeader.setBackgroundResource(R.drawable.comment_box_bg);
commentBoxHeader.setBackgroundResource(R.drawable.comment_box_header);
commentBox.addView(commentBoxHeader);
commentView.setText(array.getString(i));
LinearLayout.LayoutParams commentViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
commentViewParams.setMargins(20, 10, 20, 20);
commentView.setBackgroundResource(R.drawable.comment_bg);
commentView.setTextColor(getResources().getColor(R.color.black));
commentBox.addView(commentView, commentViewParams);
}
}//end if key is == 1
else{
// Error in registration
registerErrorMsg.setText(json2.getString(KEY_ERROR_MSG));
}//end else
}//end if
} //end try
catch (JSONException e) {
e.printStackTrace();
}//end catch
}
}
doInBackGround : method is used as a Thread !
onPostExecute : acts as a UI Thread !
So try to put your any-long running code in , doInBackGround method !
When an asynchronous task is executed, the task goes through 4 steps:
From the Docs :
onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Related
//Creating a window of ten items
WindowedStream<ObservationEvent,Tuple,GlobalWindow> windowStream = inputStream.keyBy("rackId").countWindow(10);
// Applying a Window Function , adding some custom evaluating all the values in the window
DataStream<ObservationEvent> inactivityStream = windowStream.apply(new WindowFunction<ObservationEvent, ObservationEvent , Tuple , GlobalWindow>() {
#Override
public void apply(Tuple tuple, GlobalWindow timeWindow, Iterable<ObservationEvent> itr, Collector<ObservationEvent> out)
//custom evaluation logic
out.collect(new ObservationEvent(1,"temperature", "stable"));
}
});
//Defining Simple CEP Pattern
Pattern<ObservationEvent, ?> inactivityPattern = Pattern.ObservationEvent>begin("first")
.subtype(ObservationEvent.class)
.where(new FilterFunction<ObservationEvent>() {
#Override
public boolean filter(ObservationEvent arg0) throws Exception {
System.out.println( arg0 ); //This function is not at all called
return false;
}
});
PatternStream<ObservationEvent> inactivityCEP = CEP.pattern(inactivityStream.keyBy("rackId"), inactivityPattern);
When I run this code, the filter function inside the where clause is not at all getting called.
I have printed the inactivityStream.print() and I can see the matching value.
Now, when I plug in the inputStream directly without applying a window. The pattern is matching
I printed inputStream and WindowedStream and I can see they both send similar kind of data.
What am I missing
The FilterFunction should be getting called eventually but you are going to have to wait for 10 events for the SAME key before you see your FilterFunction called for the first time. Could it be that you are just not waiting long enough in your windowing test?
Keep in mind that if you have many unique keys this implies you will have to wait well more than 10 times as long in the window test before you'll see your filter function called.
We are working on a windows application which caters to an engineering calculation which are essentially very long running. So we are basically trying to keep the calculation module separate and working in a separate worker thread and pass it an Action delegate in method signature which will be invoked to report the calculation progress in the UI. The delegate handler declared in the UI will be updating the UI. We found that while a huge loop is running in the calculation, the UI is not showing the periodic progress and only displaying the final result. If a Thread Sleep for 1 millisecond is introduced in the calculation loop, the UI is getting updated correctly. This is not expected behavior as we are executing the calculation using a separate Task and updating the UI using BeginInvoke calls.
I have created a simple application to demonstrate our approach and code so that it is easier to understand. It is obvious that we are missing something very simple but cannot quite pin it down. Will appreciate any insights.
Thanks for reading.
private void cmdStart_Click(object sender, EventArgs e)
{
txtResultDIsplay.Text = "";
var maxIterations = long.Parse(txtIterationNo.Text.Trim());
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task<double> calculationTask = Task.Factory.StartNew<double>(
() => SumRootN(maxIterations, UpdateProgress));
var handleResultTask = calculationTask.ContinueWith((t) => DisplayResult(t),
CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, ui);
}
private void DisplayResult(Task<double> calculationTask)
{
txtResultDIsplay.Text = "Final Calculation Result : " + calculationTask.Result.ToString();
}
private void UpdateProgress(string msg)
{
this.BeginInvoke((MethodInvoker)delegate
{
txtResultDIsplay.Text = msg;
});
}
public double SumRootN(long maxIterations, Action<string> progressUpdateDelegate)
{
int root = 20;
double result = 0;
for (long i = 1; i < maxIterations; i++)
{
Thread.Sleep(1);
result += Math.Exp(Math.Log(i) / root);
progressUpdateDelegate(result.ToString("0.00000"));
}
return result;
}
It is possible you are flooding the UI thread with your progress updates. You need to find a way to prevent lots of updates occurring.
We can solve the problem using tasks!
Task progressTask = null;
private void UpdateProgress(string msg)
{
//only schedule work if the task if not running
if(progressTask == null || progressTask.IsCompleted) //updates will end if there is an exception!
{
//Create a task representing the update
progressTask = Task.Factory.FromAsync<object>(BeginInvoke(new Action(() => txtResultDIsplay.Text = msg)), this.EndInvoke)
.ContinueWith(() => System.Threading.Thread.Sleep(100)); //add a sleep on the end
}
}
Note that locking will not do here as you want to skip the update if there is already an update occurring.
this is my first question in this forum, hope it will not be duplicated somewhere because i have searched for the respons for almost 4 weeks without making any progress.
here is my situation,
im developing an application that need to do a lot of background operation, for that reason i creat 2 BKW, the first one used to load data from a DB and put it inside an observable collection , 'no need to report progress or support cancelation for this one' :
private Boolean loadTestSteps()
{
// Create a background worker thread that don't report progress and does not
// support cancelation
BackgroundWorker wk_LoadTestSteps = new BackgroundWorker();
wk_LoadTestSteps.DoWork += new DoWorkEventHandler(wk_LoadTestSteps_DoWork);
wk_LoadTestSteps.RunWorkerAsync();
return true;
}
observable collection class :
public class clsTestStep : DependencyObject
{
public static DependencyProperty TestStepProperty = DependencyProperty.Register(
"TestStep", typeof(String), typeof(clsTestStep));
public string TestStep
{
get { return (string)GetValue(TestStepProperty); }
set { SetValue(TestStepProperty, value); }
} and so on for the rest of items....
now the main backGround that should do the longer operation and in the same time report the progress to the main UI ,declared like so
private void InitializeBackGroundWork()
{
_wk_StartTest = new BackgroundWorker();
// Create a background worker thread that ReportsProgress &
// SupportsCancellation
// Hook up the appropriate events.
_wk_StartTest.DoWork += new DoWorkEventHandler(_wk_StartTest_DoWork);
_wk_StartTest.ProgressChanged += new ProgressChangedEventHandler
(_wk_StartTest_ProgressChanged);
_wk_StartTest.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(_wk_StartTest_RunWorkerCompleted);
_wk_StartTest.WorkerReportsProgress = true;
_wk_StartTest.WorkerSupportsCancellation = true;
_wk_StartTest.RunWorkerAsync();
}
in the do work events, exactly in the foreach loop i encontered an error saying : you cannot access this object because another thread own it :
void _wk_StartTest_DoWork(object sender, DoWorkEventArgs e)
{
//Loop through each test step and perform Test
foreach (clsTestStep item in _testStep)
{
Thread.Sleep(200);
temp[0] = item.TestStep;
temp[1] = item.Delay.ToString();
temp[2] = item.NumberRepetition.ToString();
temp[3] = item.Mode.ToString();
//Report % of Progress, Test step Name,and the paragraph from Class PerformTest
_wk_StartTest.ReportProgress(counter,
temp[0]);
counter += 1;
_performTest.Fdispatcher(temp, out _paragraph);
//_si.PgBarMax = Convert.ToDouble(_testStep.Count);
}
//Report completion on operation completed
_wk_StartTest.ReportProgress(counter);
}
what im missing here please, because my head is gonna explod from searching !!!
It sounds like your ObservableCollection is created and so owned by an other thread so your _wk_StartTest_DoWork method can't access it.
Where your _testStep variable comes from ?
By the way, in a multithread environment when many thread access the same data you should prefer the use of ConcurrentBag class instead of an ObservableCollection. ConcurrentBag is thread safe.
for the ones that may enconter this kind of problem ^^
finnaly i have found a way to acess class even if its not owned by the current thread here a nice article explaining step by step how to do this here
I'm using a Threading.Timer to execute a task on the hour every hour, but when the timer ticks, the app always crashes when processing the code to execute in the tick. It crashes with no exceptions or warnings, even if I put the whole thin in a try/catch. Very strange. Below is my setup and any help would be appreciated! It seems like crashes when it tries to access the TextBox GrepCmdTextBox, but I thought reading from another thread was okay, just not writing.
Setting up timer:
var timeOfDay = DateTime.Now.TimeOfDay;
var nextHour = TimeSpan.FromHours(Math.Ceiling(timeOfDay.TotalHours));
var delta = (nextHour - timeOfDay).TotalMilliseconds;
System.Threading.Timer NextHourTimer = new System.Threading.Timer(new System.Threading.TimerCallback(NextHourTimer_Tick), null, (long)delta, (long)TimeSpan.FromHours(1).TotalMilliseconds);
Tick event:
private void NextHourTimer_Tick(object sender)
{
// If thread is not null and is busy, cancel and restart
if (MonitoringThread != null)
{
if (MonitoringThread.TailThread.IsBusy)
{
MonitoringThread.TailThread.CancelAsync();
System.Threading.Thread.Sleep(50);
// Get grep command, if specified
string optionalGrep = String.Empty;
if (GrepCmdTextBox.Text.StartsWith("grep") || GrepCmdTextBox.Text.StartsWith("egrep"))
optionalGrep = " | " + GrepCmdTextBox.Text;
MonitoringThread.TailThread.RunWorkerAsync(optionalGrep);
}
}
}
Cancelling the asynchronous process can take time, the background thread will have to 'finalize', returning from DoWork() and waiting for an opportunity to run the RunWorkerCompleted event, if any.
Instead of cancellation, in this case it would be better to cancel then Dispose() the object, creating a new BGW, as they are as 'cheap-as-chips'.
I hope this helps.
I'm web developer and I'm trying to step into multithreading programming.
On one form I'm trying to run a method computing values in a second thread using asynchronous delegates.
I also want a progress bar showing actual progress in UI thread been notified.
delegate void ShowProgressDelegate(int total, int value);
delegate void ComputeDelegate(int value);
//Some method simulating sophisticated computing process
private void Compute(int value)
{
ShowProgress(value, 0);
for (int i = 0; i <= value; i++)
{
ShowProgress(value, i);
}
}
//Method returning values into UI thread
private void ShowProgress(int total, int value)
{
if (!this.InvokeRequired)
{
ComputeButton.Text = value.ToString();
ProgressBar.Maximum = total;
ProgressBar.Value = value;
}
else
{
ShowProgressDelegate showDel = new ShowProgressDelegate(ShowProgress);
this.BeginInvoke(showDel, new object[] { total, value });
}
}
//firing all process
private void ComputeButton_Click(object sender, EventArgs e)
{
ComputeButton.Text = "0";
ComputeDelegate compDel = new ComputeDelegate(Compute);
compDel.BeginInvoke(100000, null, null);
}
When I run this, everything is computing without any problem except it is still running in UI thread (I suppose so, because it freezes when I click some button on the form).
Why? I also attach buildable sample project (VS2010) with same code: http://osmera.com/windowsformsapplication1.zip
Thanks for helping neewbie.
In the code you've shown, you're doing nothing other than updating the progress bar - so there are thousands of UI messages to marshal, but nothing significant happening in the non-UI thread.
If you start simulating real work in Compute, you'll see it behave more reasonably, I suspect. You need to make sure you don't swamp the UI thread with progress updates like you are doing now.