In addition to the UI thread, multi-thread processing of Bitmaps and uibitmaps

Source: Internet
Author: User

In addition to the UI thread, multi-thread processing of Bitmaps and uibitmaps
Multi-thread processing of Bitmaps
In the previous article, we discussed: Android can effectively process Bitmap and reduce memory, but it is best not to execute it in the main thread (UI thread ), if the image is local, network, or somewhere else. The image loading time is related to many factors (such as reading speed from the network or local, image size, CPU capability). If these tasks block the UI thread, the system may recycle and close it (see Designing for Responsiveness for more information ). this article will discuss how to use AsyncTask in the background outside the UI thread to add Bitmap (images of local or network images or other resources) and ask you how to process them concurrently. Address: http://wear.techbrood.com/training/displaying-bitmaps/process-bitmap.html
Asynchronous tasks provide a convenient way to implement interaction between UI threads and background threads. We can derive a class and override its method. The following is an example of loading a large image to ImageView, using the previous drop-down technology decodeSampledBitmapFromResource () (please refer to the previous content http://blog.csdn.net/liu8497/article/details/40786721 ):

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {    private final WeakReference<ImageView> imageViewReference;    private int data = 0;    public BitmapWorkerTask(ImageView imageView) {        // Use a WeakReference to ensure the ImageView can be garbage collected        imageViewReference = new WeakReference<ImageView>(imageView);    }    // Decode image in background.    @Override    protected Bitmap doInBackground(Integer... params) {        data = params[0];        return decodeSampledBitmapFromResource(getResources(), data, 100, 100));    }    // Once complete, see if ImageView is still around and set bitmap.    @Override    protected void onPostExecute(Bitmap bitmap) {        if (imageViewReference != null && bitmap != null) {            final ImageView imageView = imageViewReference.get();            if (imageView != null) {                imageView.setImageBitmap(bitmap);            }        }    }}

Use WeakReference to save the ImageView. This ImageView still exists at the end of the asynchronous task, but it cannot be well recycled by the memory. Therefore, you must check whether the ImageView is empty in onPostExecute. The ImageView may be empty. For example, when the Activity exits or other configurations change before the asynchronous task exits
To start loading a Bitmap, you only need to instantiate a task and execute it:
public void loadBitmap(int resId, ImageView imageView) {    BitmapWorkerTask task = new BitmapWorkerTask(imageView);    task.execute(resId);}

Common components of parallel processing, such as ListView and GridView introduce other problems when combined with asynchronous tasks. In order to better use the memory, the user starts to recycle other sub-views when scrolling. If each sub-View uses an asynchronous task, we cannot guarantee that the associated view is not recycled when the asynchronous task ends. We cannot guarantee that asynchronous tasks are executed in our order. There is a blog post Multithreading for Performance, which discusses the problem of parallel processing in depth and provides a solution. Its ImageView points to the most recent asynchronous task, the task can be verified and executed after the task is completed. Using the same method, the asynchronous task mentioned above can follow a similar route. Create a dedicated Drawable to store resources pointing to the task. Therefore, we use BitmapDrawable to display the image at the end of the task in ImageView:
static class AsyncDrawable extends BitmapDrawable {    private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;    public AsyncDrawable(Resources res, Bitmap bitmap,            BitmapWorkerTask bitmapWorkerTask) {        super(res, bitmap);        bitmapWorkerTaskReference =            new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);    }    public BitmapWorkerTask getBitmapWorkerTask() {        return bitmapWorkerTaskReference.get();    }}
In execution Before BitmapWorkerTask, We can bind an AsyncDrawable to the ImageView.
public void loadBitmap(int resId, ImageView imageView) {    if (cancelPotentialWork(resId, imageView)) {        final BitmapWorkerTask task = new BitmapWorkerTask(imageView);        final AsyncDrawable asyncDrawable =                new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);        imageView.setImageDrawable(asyncDrawable);        task.execute(resId);    }}

CancelPotentialWork this method checks whether other tasks are associated with this ImageView. If yes, use the cancel () function to cancel the associated task. In rare cases, the data of the new task matches and interacts with the previous one. The implementation of cancelPotentialWork is as follows:
public static boolean cancelPotentialWork(int data, ImageView imageView) {    final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);    if (bitmapWorkerTask != null) {        final int bitmapData = bitmapWorkerTask.data;        // If bitmapData is not yet set or it differs from the new data        if (bitmapData == 0 || bitmapData != data) {            // Cancel previous task            bitmapWorkerTask.cancel(true);        } else {            // The same work is already in progress            return false;        }    }    // No task associated with the ImageView, or an existing task was cancelled    return true;}

An auxiliary method getBitmapWorkerTask () is used to retrieve tasks related to ImageView.
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {   if (imageView != null) {       final Drawable drawable = imageView.getDrawable();       if (drawable instanceof AsyncDrawable) {           final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;           return asyncDrawable.getBitmapWorkerTask();       }    }    return null;}
In the last step, onPostExecute () is updated in BitmapWorkerTask to check whether the task is canceled and whether the current task matches the ImageView:
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {    ...    @Override    protected void onPostExecute(Bitmap bitmap) {        if (isCancelled()) {            bitmap = null;        }        if (imageViewReference != null && bitmap != null) {            final ImageView imageView = imageViewReference.get();            final BitmapWorkerTask bitmapWorkerTask =                    getBitmapWorkerTask(imageView);            if (this == bitmapWorkerTask && imageView != null) {                imageView.setImageBitmap(bitmap);            }        }    }}
Now, we can use Asynchronous tasks to effectively Recycle resources in ListView and GridView or other components. We only need to execute loadBitmapYou can put an image in the ImageVIew. For example, in the GridVIew, we use this method in the getView method of the Adapter.

C # multi-threaded UI with No Response

Because you are using multithreading, you cannot directly operate the controls in the main thread in the Child thread,
Your main problem code here InvokeRequired blocks the ui thread.
Please take a closer look at the following content.
The most important thing to note when using multithreading in Windows Form is that apart from creating the control thread, do not call control members in any other thread (except for a few cases). That is to say, the control belongs to the thread that creates it and cannot be accessed from other threads. This applies to all controls derived from System. Windows. Forms. Control (so it can be said that almost all controls), including the Form Control itself. The child control of the control must be created by the control creation thread, such as a button on the form, such as the form creation thread. Therefore, all controls in a window are actually in the same thread. In actual programming, most software practices allow the same thread to take charge of all controls. This is what we call the UI thread.
When you never call a member of a control created by a non-thread in any other thread, it also says "only a few exceptions ", this Invoke method is one of the most common cases-the Invoke method can be called from any thread.
The parameters of the Invoke method are very simple, a delegate and a parameter table (Optional). The main function of the Invoke method is to help you in the UI thread (that is, to create the control thread) the method specified by the delegate. The Invoke method first checks whether the calling thread (that is, the current thread) is a UI thread. If yes, it directly executes the method pointed to by the delegate. If not, it switches to the UI thread, then execute the delegate pointing method. Regardless of whether the current thread is a UI thread, Invoke is blocked until the execution of the method pointed to by the delegate is completed, and then the call thread is switched back (if needed) to return. Note: when using the Invoke method, the UI thread cannot be in the blocking state.
However, the BeginInvoke method of the Control always uses the UI thread, while other asynchronous delegate call methods use the thread in the thread pool. Compared with Invoke, it is a little more troublesome to use BeginInvoke, but in that sentence, Asynchronization is better than synchronization, although it is more complicated. For example, a deadlock may occur in the synchronous method: when the worker thread synchronously calls the methods in the UI thread through Invoke, what if the UI thread is waiting for the worker thread to do something? Therefore, the asynchronous method should be used whenever possible.
You can solve the problem by referring to the addresses listed in the image below.




C # winform multithread asynchronous UI update

First, put a button and a picturebox on the form.
(Picturebox visible is false) The purpose of this multithreading is to click the button and the image runs normally, and the other thread runs after 10 seconds of sleep.
Private void button#click (object sender, EventArgs e)
{
// Enable the thread
System. Threading. Thread thread = new System. Threading. Thread (new System. Threading. ThreadStart (this. Result ));
PictureBox1.Visible = true;
Button1.Enabled = false;
Thread. Start ();
}

Private void Result ()
{
Bool OK = this. Do ();
This. BeginInvoke (new System. Threading. ThreadStart (delegate ()
{
If (OK) MessageBox. Show ("successful", "prompt ");
Else MessageBox. Show ("failed", "prompt ");
PictureBox1.Visible = false;
Button1.Enabled = true;
}));
}

Private bool Do ()
{
System. Threading. Thread. Sleep (10000 );
Return true;
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.