- Home /
Can I reuse a WWWForm?
I have a bunch of small files I need to upload via WWWForm. I'd like to make a pool of them and reuse them if possible. Like if I have a queue of three WWW's uploading, each has its own WWWForm. When one is done, I want to assign another file to it and upload. I don't see a way to access the WWWForm of a WWW object. And what happens to that WWWForm anyway, is it destroyed when uploadProgress hits 1.0? If not, how is this cleaned up? Any tips?
Answer by Bunny83 · Aug 30, 2013 at 08:00 PM
There's no need to reuse them. The WWWForm class is a pure managed class with no unmanaged content. So like any other managed class it will be marked for garbage collection as soon as there's no active reference to it and will be destroyed at the next GC cycle.
When you create a WWW object (which does use unmanaged resources) it is stored internally for processing. The WWW object doesn't store a reference to the WWWForm. It's just a helper class to create the headers hashtable and the post-data array. So as soon as you called the WWW constructor the WWWForm is no longer needed.
Just an example:
// C#
IEnumerator DoSomeRequests()
{
var form = new WWWForm();
form.AddBinaryData("file", fileData);
WWW request = new WWW("myURL",form);
// at this point we don't need the WWWForm any longer but we still have
// the form variable which keeps it alive
yield return request;
// second chained request
form = new WWWForm();
// at this point the old WWWForm will be marked for collection since we've
// just overwritten the last reference to it by creating a new one.
form.AddBinaryData("file", fileData);
request = new WWW("myURL",form);
// At this point the old WWW object is ready for the GC since the reference
// to it is gone
yield return request;
// once you left this coroutine all local references to objects have reached the
// end of their lifetime so the last WWWForm and WWW object will also be marked
// for garbage collection.
}
Since the WWWForm has no way of resetting it's internal lists, you can't reuse it unless you want to send the exact same thing again.
This is the constructor of WWW that takes a WWWForm as parameter:
public WWW(string url, WWWForm form)
{
this.InitWWW(url, form.data, WWW.FlattenedHeadersFrom(form.headers));
}
InitWWW is the internal method which will actually start the request. As you can see the passed form reference is not stored anywhere. It is just used to create the post data (form.data) and the required HTTP headers (form.headers).
If you want to queue some uploads and want to process 3 at a time I would do something like this:
public class Request
{
public string url;
public WWWForm form;
public Request(string aUrl, byte[] aFileData, string aFileName)
{
url = aUrl;
form = new WWWForm();
form.AddBinaryData("file", aFileData, aFileName);
}
}
IEnumerator SendFile(LinkedList<Request> queue)
{
while(queue.Count > 0)
{
Request R = queue[0];
queue.RemoveFirst();
WWW www = new WWW(R.url, R.form);
yield return www;
}
}
void SendFiles()
{
LinkedList<Request> queue = new LinkedList<Request>();
queue.AddLast(new Request("someURL", someFileData1, "the filename1"));
queue.AddLast(new Request("someURL", someFileData2, "the filename2"));
queue.AddLast(new Request("someURL", someFileData3, "the filename3"));
queue.AddLast(new Request("someURL", someFileData4, "the filename4"));
queue.AddLast(new Request("someURL", someFileData5, "the filename5"));
queue.AddLast(new Request("someURL", someFileData6, "the filename6"));
//...
StartCoroutine(SendFiles(queue));
StartCoroutine(SendFiles(queue));
StartCoroutine(SendFiles(queue));
}
Here i start 3 coroutines at once and each one will pick a request from the same list. So where are 3 concurrent requests at a time. If one request is finished the coroutine will pick the next one until there are no requests pending and the coroutines will terminate.
Once the coroutines are finished all objects we have created will be garbage collected.
That helps a lot thanks. WWW is not managed, so if I have a lot of them, do they get GC'd or do I have to worry about that?
The unmanaged resources get cleaned up when they are no longer needed. The WWW class has actually both: a managed part and an unmanaged part. $$anonymous$$ost of the actual data is handled in native code (unmanaged). The managed part is mainly just a collection of functions which are mapped to native functions. All of those dual-object-types are tracked on both sides. However if you loose all references in your managed code, Unity can detect this and clean up the unmanaged part as well.
There are a few of these kind of objects which work differently. For example the GameObject. Even if you don't have a reference to a GameObject it is still there. That's because those objects are "searchable" so you can get a new reference to the object (or maybe a new one is created if the managed part wasn't there, who knews).
Back to the WWW object you can explicitly call "Dispose" on the object once you're done. That will destroy the unmanaged part of the object and would also ter$$anonymous$$ate the request if one is still pending.
If you plan to trigger a lot downloads / uploads in a short time (50+) you should call Dispose after the request has finished, that ensures an immediate cleanup of the unmanaged resources.
The managed part is, like always, destroyed by the GC once you lost all references to it. In my SendFile coroutine i have a local reference to the WWW object (in line 19). As long as this reference references the WWW object it can't be collected. However if the coroutine processes the second request (so the next while loop iteration) it will overwrite the reference with a reference to a new WWW object which effectively discard the old reference and the old WWW object can be collected.
Once the last request is done the coroutine finishes and since www is a local variable it is gone once the routine has ended.
Your answer
Follow this Question
Related Questions
uploading png with wwwform 0 Answers
Upload large files 0 Answers
Failed to upload image over custom server 3 Answers
Why isn't this $_POST working properly? 1 Answer
Blank web server response in multiple type data submission 1 Answer