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?

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.