Multi-threaded application w/ system.io.packaging

F

Frank Prevatt

I have a C# class that has a method which takes a list of files and creates a
zip file using the system.io.packaging.package class. It is called from
another class in another project which creates the files to be packaged. This
in turn is called by a WCF service.

What I am finding is that when a single call is made to the zipping
component, it works fine. However, if it is called by different instances of
the component, it locks up on copying the stream to the package.

Here is the code for the ZipComponents method...with it's CopyStream
subroutine:

public void ZipComponents()
{
try
{
string zipFile = Path.ChangeExtension(fileName, "zip");
int fileNumber = 0;
using (Package exportPackage = Package.Open(zipFile,
FileMode.Create))
{
foreach (string file in componentFiles)
{
string tempFilePath =
file.Split("|".ToCharArray())[0];
string originalFileName =
file.Split("|".ToCharArray())[1];

fileNumber++;

Uri partUriDocument =
PackUriHelper.CreatePartUri(new Uri(fileNumber.ToString() + "-" +
originalFileName, UriKind.Relative));

PackagePart packagePart =
exportPackage.CreatePart(partUriDocument, "video/asf");

using (FileStream fileStream =
File.OpenRead(tempFilePath))
{

using (Stream packageStream =
packagePart.GetStream())
{
CopyStream(fileStream, packageStream);
}

}

string hashFile = Path.ChangeExtension(tempFilePath,
"hsh");
string originalHashName =
Path.ChangeExtension(originalFileName, "hsh");

partUriDocument = PackUriHelper.CreatePartUri(new
Uri(fileNumber.ToString() + "-" + originalHashName, UriKind.Relative));

packagePart =
exportPackage.CreatePart(partUriDocument, "text/hash");

using (FileStream fileStream =
File.OpenRead(hashFile))
{

using (Stream packageStream =
packagePart.GetStream())
{
CopyStream(fileStream, packageStream);
}

}
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry("Archive Service", "Error zipping " +
fileName + "\n" + ex.ToString(), EventLogEntryType.Error);
}
}

private static void CopyStream(Stream source, Stream target)
{
const int bufSize = 0x1000;
byte[] buf = new byte[bufSize];
int bytesRead = 0;
while ((bytesRead = source.Read(buf, 0, bufSize)) > 0)
target.Write(buf, 0, bytesRead);
source.Flush();
target.Flush();
}

Any insight would be apprecitated.
 
P

Peter Duniho

Frank said:
I have a C# class that has a method which takes a list of files and creates a
zip file using the system.io.packaging.package class. It is called from
another class in another project which creates the files to be packaged. This
in turn is called by a WCF service.

What I am finding is that when a single call is made to the zipping
component, it works fine. However, if it is called by different instances of
the component, it locks up on copying the stream to the package.

[....]
Any insight would be apprecitated.

Very little insight can be provided, given your failure to provide a
concise-but-complete code example. However, there's really no reason to
believe that you can just arbitrarily use shared data between threads
this way without doing extra work to synchronize access to the data.
This would include files that may be accessed simultaneously by
different threads.

So it seems to me that the most obvious answer is: stop doing that.
Synchronize your code so that multiple threads don't interfere with each
other when they attempt to use shared data.

If you want more specific advice, post a concise-but-complete code
example that reliably demonstrates the problem. Then, we'll be able to
see in a precise way where and how your code is shared data in a
thread-unsafe way, why that causes the program to fail, and offer more
specific information about the appropriate way to synchronize access to
that data in the least-obtrusive way.

Pete
 
F

Frank Prevatt

Thank you for you quick reply. I apologize for being unclear. This class
resides in a library. Another external library instantiates this class. Each
instance of this class is zipping files that are unique to the instance.
There are no shared files/data. There is a unique folder with files to be
zipped and the zip file is being created there as well. At no time do files
get touched by more than one instance of this class. Yet, as I mentioned,
when two or more instances of this class are running (zipping files in unique
directories), all but one instance will hang on the CopyStream method.

Peter Duniho said:
Frank said:
I have a C# class that has a method which takes a list of files and creates a
zip file using the system.io.packaging.package class. It is called from
another class in another project which creates the files to be packaged. This
in turn is called by a WCF service.

What I am finding is that when a single call is made to the zipping
component, it works fine. However, if it is called by different instances of
the component, it locks up on copying the stream to the package.

[....]
Any insight would be apprecitated.

Very little insight can be provided, given your failure to provide a
concise-but-complete code example. However, there's really no reason to
believe that you can just arbitrarily use shared data between threads
this way without doing extra work to synchronize access to the data.
This would include files that may be accessed simultaneously by
different threads.

So it seems to me that the most obvious answer is: stop doing that.
Synchronize your code so that multiple threads don't interfere with each
other when they attempt to use shared data.

If you want more specific advice, post a concise-but-complete code
example that reliably demonstrates the problem. Then, we'll be able to
see in a precise way where and how your code is shared data in a
thread-unsafe way, why that causes the program to fail, and offer more
specific information about the appropriate way to synchronize access to
that data in the least-obtrusive way.

Pete
.
 
P

Peter Duniho

Frank said:
Thank you for you quick reply. I apologize for being unclear. This class
resides in a library. Another external library instantiates this class. Each
instance of this class is zipping files that are unique to the instance.
There are no shared files/data. There is a unique folder with files to be
zipped and the zip file is being created there as well. At no time do files
get touched by more than one instance of this class. Yet, as I mentioned,
when two or more instances of this class are running (zipping files in unique
directories), all but one instance will hang on the CopyStream method.

Assuming your description of the problem is correct, then all of those
assumptions you've made about the class instances being completely
independent of each other are clearly incorrect. Windows or .NET don't
just go around randomly and indefinitely suspending operations in
classes that are correctly written.

So, either you're observing the problem wrong, or you're judging the
state of the code wrong. Possibly both are true.

Either way, a concise-but-complete code example would clear things up
quickly, and without such a code example, there's little hope of you
getting much in the way of useful advice.

Pete
 
B

bryce.drew

Was there ever a solution found for this?
I am finding a very similar issue (code all works fine with one instance of zipping; works fine with multiple instances unless the input file is larger than 11Mb, at which point everything hangs up).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top