Queue.Dequeue() causes exception "Object reference not set to aninstance of an object."

A

alexia

Hi all,

I wrote a simple test app which using the Queue object. In some reson,
after several calling to Dequeue() I get this exception.
I have to threads. One thread adds to queue and the other removes from
queue.
I saw that the Queue is not ampty and if after the exception I call
Dequeue() again I don't get the exception.
Here is my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;

namespace queueTest
{
class Program
{
static Queue Q = new Queue();
static AutoResetEvent resEvent = new AutoResetEvent(false);

static void Main(string[] args)
{
Thread thrdA = new Thread(threadFunA);
Thread thrdB = new Thread(threadFunB);
thrdB.Start();
thrdA.Start();

Thread.Sleep(100000);
}

static void threadFunA()
{
int i = 1;
while (true)
{
Q.Enqueue(i);
Console.WriteLine("Writing: " + i.ToString());
resEvent.Set();
//If I put Thread.Sleep(1); the exception doesn't
happen.
i++;
}
}

static void threadFunB()
{
Queue sincQ = Queue.Synchronized(Q);
while (true)
{
try
{
resEvent.WaitOne();
Console.WriteLine("Reading: " + sincQ.Dequeue
().ToString());
}
catch (Exception e)
{
Console.WriteLine("Errror: " + e.Message);
}
}
}
}
}

Thanks for your help.
 
P

Peter Duniho

alexia said:
Hi all,

I wrote a simple test app which using the Queue object. In some reson,
after several calling to Dequeue() I get this exception.
I have to threads. One thread adds to queue and the other removes from
queue.
I saw that the Queue is not ampty and if after the exception I call
Dequeue() again I don't get the exception. [...]

I would say that the most obvious problem with your code is that you are
using a different queue in one thread than you are in the other. In
other words, access to the queue isn't synchronized at all, because only
one thread is using the synchronized wrapper.

This means that the producer thread could be in the process of changing
the underlying data structures at the same time your consumer thread
tries to dequeue an item. If the consumer thread makes that attempt at
just the wrong time, the queue could _appear_ to be empty at the instant
the consumer thread calls Dequeue() (i.e. that method will return
"null"), even though it's not.

Adding a call to Sleep() ensures with almost 100% certainty that the
consumer thread will consume the newly added item before the producer
thread gets to try to add another. Emphasis on "almost"...in a
worst-case scenario, it could still fail. It's just a LOT less likely.

Your other significant bug is that your consumer thread only dequeues
one item per signaling of the AutoResetEvent. But the producer thread
could have enqueued more than one item (and in fact almost certainly
will have) before the consumer thread even gets a chance to wake up and
dequeue an item. The consumer thread will fall farther and farther
behind the longer you let this code run.

I strongly recommend the Monitor class, and its Wait() and Pulse()
methods for dealing with this sort of producer/consumer scenario (and
for similar scenarios, for that matter). It's nice that .NET provides
the EventHandle classes mirroring the commonly-used unmanaged event
handle API. But Monitor is slightly more efficient and provides what
IMHO are better semantics for the synchronization of the two threads.

You can also use Monitor with the same synchronization object to achieve
both synchronization of access to the queue as well as signaling between
the producer and consumer thread, rather than having to use two separate
mechanisms for each requirement as your code does (or rather, tries to
do) now.

(Not that using Monitor will inherently rid your code of the second bug
I mentioned. Just that I find the Monitor class nicer to use).

In any case, at the very least you need to fix your code so that there
is some actual synchronization between the producer and consumer
threads' access of the queue. Currently there is none at all.

Pete
 
A

alexia

Hello Pete,
Thank you for your reply.

Why do you think I am using a different queue? I saw that the consumer
(threadFunB() function ) dequeues the items the producer added in FIFO
way.
I am using the Synchronized() function as shown in MSDN. I must admit
that I didn't fully understood its purpose.
What I understand is that its suppose to make my queue to thread safe,
which what you claim that my code is not
thread safe. Acording to MSDN sample, only the consumer suppose to use
the Synchronized() function.

One more thing I noticed is that if I don't use the eventhadler and
let the consumer continue dequeue I don't get this exception but i do
get queue empty exception
which is easy to handle.
This means that the producer thread could be in the process of changing
the underlying data structures at the same time your consumer thread
tries to dequeue an item. If the consumer thread makes that attempt at
just the wrong time, the queue could _appear_ to be empty at the instant
the consumer thread calls Dequeue() (i.e. that method will return
"null"), even though it's not.

Why do you think that in that case the queue could _appear_ to be
empty? isn't that the purpose of the Synchronized() function to make
it thread safe?
Your other significant bug is that your consumer thread only dequeues
one item per signaling of the AutoResetEvent. But the producer thread
could have enqueued more than one item (and in fact almost certainly
will have) before the consumer thread even gets a chance to wake up and
dequeue an item. The consumer thread will fall farther and farther
behind the longer you let this code run.

You are RIGHT about that the consumer fall back after the producer.
The consumer doesn't consume fast enough. I get the exception where
the consumer dequeues 4381 items while the producer enqueues 37265
items.

Is there any chance that there is a bug in the Queue object?

Thank you for your help.
 
P

Peter Duniho

alexia said:
Hello Pete,
Thank you for your reply.

Why do you think I am using a different queue?

Because you are. To be more specific: the underlying queue data
structure is the same, but you are not using the same instance of the
Queue class in each thread. Compare the two references ("Q" and
"sincQ") used in each if you don't believe me (e.g.
Object.ReferenceEquals()).
I saw that the consumer
(threadFunB() function ) dequeues the items the producer added in FIFO
way.
I am using the Synchronized() function as shown in MSDN. I must admit
that I didn't fully understood its purpose.

From the docs: "Returns a Queue wrapper that is synchronized (thread
safe)." That's its purpose.

Also from the docs: "To guarantee the thread safety of the Queue, all
operations must be done through this wrapper only." Note: "ALL
OPERATIONS" (emphasis mine, of course).

Once you have a synchronized Queue instance, returned by the
Synchronized() method, you MUST use _that_ instance for ALL OPERATIONS
on the queue in order to maintain thread safety. The original instance
must NOT be used.

Your code uses both the original instance and the new synchronized
instance. That's directly contra-indicated by the documentation.
What I understand is that its suppose to make my queue to thread safe,

No. It doesn't make your original queue thread-safe. It returns a
_new_ instance of Queue that is thread-safe. The previous instance
remains NOT thread-safe, and in fact the new instance is also NOT
thread-safe unless you ONLY use the new instance for ALL OPERATIONS on
the queue.

Sorry if all that emphasis seems excessive; these seem to me to be very
important points that you aren't managing to notice in the documentation
for some reason, so I'm trying very hard to make sure they don't escape
your attention at this point. :)
which what you claim that my code is not
thread safe. Acording to MSDN sample, only the consumer suppose to use
the Synchronized() function.

What sample? I could not find any sample on MSDN in which there is both
a producer and a consumer thread, and in which the producer thread uses
the original Queue instance and the consumer thread uses the
synchronized wrapper Queue instance.

I suspect that you are simply misinterpreting some example code on MSDN.
But if there's really a sample there that shows what you say it shows,
I'd like to know about it, so that I can submit a bug report on it.
One more thing I noticed is that if I don't use the eventhadler and
let the consumer continue dequeue I don't get this exception but i do
get queue empty exception
which is easy to handle.

Without the EventHandle instance, the behavior will become more random
in nature. You still run the risk of the queue returning a null
reference from the Dequeue() method, but you also get _other_ possible
bad behaviors as well (such as trying to dequeue an element from an
empty queue).
Why do you think that in that case the queue could _appear_ to be
empty? isn't that the purpose of the Synchronized() function to make
it thread safe?

First, let me correct my statement. A null return value from Dequeue()
doesn't indicate an empty queue, so that's not the appearance that the
unsynchronized access causes. Rather, you simply get the wrong value
for the dequeued element (most likely because the queue's internal
indices have been updated but the new value hasn't been copied to the
internal array yet, or vice a versa).

Second, the purpose of the Synchronized() method is exactly as I stated
before: to return a _new_ instance of Queue that is thread-safe. It
does nothing at all to the original instance.
You are RIGHT about that the consumer fall back after the producer.
The consumer doesn't consume fast enough. I get the exception where
the consumer dequeues 4381 items while the producer enqueues 37265
items.

Really? That's odd. I mean, I fully expect there to be an exception
eventually, but for it to happen so early, after enqueuing only 37000 or
so elements seems really strange (unless perhaps you are testing this
code on a computer that has very constrained memory and disk space).
Is there any chance that there is a bug in the Queue object?

No. There is practically no chance at all that there is a bug in the
Queue class. There is, however, an obvious and definite bug in your
code. The code simply is not thread-safe.

Pete
 
A

alexia

Because you are.  To be more specific: the underlying queue data
structure is the same, but you are not using the same instance of the
Queue class in each thread.  Compare the two references ("Q" and
"sincQ") used in each if you don't believe me (e.g.
Object.ReferenceEquals()).


 From the docs: "Returns a Queue wrapper that is synchronized (thread
safe)."  That's its purpose.

Also from the docs: "To guarantee the thread safety of the Queue, all
operations must be done through this wrapper only."  Note: "ALL
OPERATIONS" (emphasis mine, of course).

Once you have a synchronized Queue instance, returned by the
Synchronized() method, you MUST use _that_ instance for ALL OPERATIONS
on the queue in order to maintain thread safety.  The original instance
must NOT be used.

Your code uses both the original instance and the new synchronized
instance.  That's directly contra-indicated by the documentation.


No.  It doesn't make your original queue thread-safe.  It returns a
_new_ instance of Queue that is thread-safe.  The previous instance
remains NOT thread-safe, and in fact the new instance is also NOT
thread-safe unless you ONLY use the new instance for ALL OPERATIONS on
the queue.

Sorry if all that emphasis seems excessive; these seem to me to be very
important points that you aren't managing to notice in the documentation
for some reason, so I'm trying very hard to make sure they don't escape
your attention at this point.  :)


What sample?  I could not find any sample on MSDN in which there is both
a producer and a consumer thread, and in which the producer thread uses
the original Queue instance and the consumer thread uses the
synchronized wrapper Queue instance.

I suspect that you are simply misinterpreting some example code on MSDN.
  But if there's really a sample there that shows what you say it shows,
I'd like to know about it, so that I can submit a bug report on it.


Without the EventHandle instance, the behavior will become more random
in nature.  You still run the risk of the queue returning a null
reference from the Dequeue() method, but you also get _other_ possible
bad behaviors as well (such as trying to dequeue an element from an
empty queue).



First, let me correct my statement.  A null return value from Dequeue()
doesn't indicate an empty queue, so that's not the appearance that the
unsynchronized access causes.  Rather, you simply get the wrong value
for the dequeued element (most likely because the queue's internal
indices have been updated but the new value hasn't been copied to the
internal array yet, or vice a versa).

Second, the purpose of the Synchronized() method is exactly as I stated
before: to return a _new_ instance of Queue that is thread-safe.  It
does nothing at all to the original instance.



Really?  That's odd.  I mean, I fully expect there to be an exception
eventually, but for it to happen so early, after enqueuing only 37000 or
so elements seems really strange (unless perhaps you are testing this
code on a computer that has very constrained memory and disk space).


No.  There is practically no chance at all that there is a bug in the
Queue class.  There is, however, an obvious and definite bug in your
code.  The code simply is not thread-safe.

Pete

Hello Pete again,

Thank you for your reply. Now I understand what is the reason for the
Synchronized() function.
Basically I wanted to use the Queue for IPC. I thought that the Queue
class can serve as some kind of cyclic buffer without locking.
I am currently using socket as IPC.

Thanks you again.
 
N

not_a_commie

Locking (aka, the Monitor class) would be way faster than using an
AutoResetEvent. Them suckers are slow. Here, I've modified your code
(but not tested it) to do what I believe you wanted:

namespace queueTest
{
    class Program
    {
        static Queue Q = Queue.Synchronized();

        static void Main(string[] args)
        {
            Thread thrdA = new Thread(threadFunA);
            Thread thrdB = new Thread(threadFunB);
            thrdB.Start();
            thrdA.Start();

            Thread.Sleep(100000);
        }

        static void threadFunA()
        {
            int i = 1;
lock(Q.SyncLock)
            while (true)
            {
                Q.Enqueue(i);
                Console.WriteLine("Writing: " + i.ToString());
Monitor.Pulse(Q.SyncLock);
                i++;
            }
        }

        static void threadFunB()
        {
lock(Q.SyncLock)
            while (true)
            {
               Monitor.Wait(Q.SyncLock);
              Console.WriteLine("Reading: " + Q.Dequeue().ToString
());
            }
        }
    }
}

Be sure to remove teh WriteLine calls for any performance
measurements. You should probably read through this thread:
http://groups.google.com/group/micr...6?lnk=gst&q=class+bransmutex#995c7921d4b8e436
 
P

Peter Duniho

alexia said:
Thank you for your reply. Now I understand what is the reason for the
Synchronized() function.
Basically I wanted to use the Queue for IPC.

Define "IPC". Normally, "IPC" means "inter-process communication",
which precludes in-process data structures as being sufficient for the
communication.

If you expect to use the Queue class for IPC, it seems that you are
using that abbreviation to mean something else.
I thought that the Queue
class can serve as some kind of cyclic buffer without locking.

You can use the Queue instance returned by the Synchronized() method to
accomplish thread-safe access to the queue without any _explicit_
locking. But remember that internal to the synchronized Queue is a
synchronized implementation, which generally implies some kind of
locking (it's possible to write a lock-free data structure, of course,
but I can see looking at the implementation of the synchronized Queue
that all it does is use the "lock" statement, which is a C# short-hand
for using the Monitor class).
I am currently using socket as IPC.

If by "IPC" you mean "inter-process communication", then that's a fairly
good, common, and efficient way to accomplish that and the Queue class
cannot in and of itself replace that technique. If you mean something
else, well...it's possible a Queue would be appropriate, or not. You'll
need to define "IPC" for us to be sure.

Pete
 
P

Peter Duniho

not_a_commie said:
Locking (aka, the Monitor class) would be way faster than using an
AutoResetEvent. Them suckers are slow. [...]

Monitor is faster, but it's not _that_ much faster. I benchmarked the
two recently, and even allocating and disposing a new EventHandle for
each sychronization iteration, it only slowed the code down by about 20%
when there was practically no additional work being done (just
incrementing a counter).

Caching the object closed the gap somewhat. And for synchronization of
non-trivial code, the cost of the synchronized code will tend to obscure
the performance difference between EventHandle and Monitor even further.

I agree that Monitor is preferable (and said so in my earlier replies to
the OP), but it's not a large enough speed improvement to justify
avoiding an EventHandle if the code for some reason otherwise works
better with that approach (in this case it doesn't, but in other
scenarios it very well may).

Pete
 
N

newbie18

Hi All,

I'm using almost the same approach as alexia in using Queue. However,
I'm not using any synchronize queue.

The sample code as follow has been running for about a year, but
recently I encounter "Object reference not set to an instance of an
object" error. Wondering would it be cause by the Queue. This error is
occurred at Process function in cSocket class. Please advise.

Imports System.Text
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading

Public Class Service
Dim aThread As Threading.Thread
Dim objSoc As cSocket

Public Sub StartProcess()
Try
objSoc = New cSocket()
aThread = New Threading.Thread(AddressOf objSoc.Listen)
aThread.Start()
Catch ex As Exception
Console.WriteLine("StartProcess:" & ex.Message)
End Try


Try
objSoc.Process()
Catch ex1 As Exception
Console.WriteLine("StartProcess:" & ex1.Message)
End Try
End Sub

End Class


Public Class cSocket

Private Que As System.Collections.Queue
Private socListener As Socket
Private socClient As Socket
Private localEndPoint As IPEndPoint

Public Sub New()
Dim intQueSize As Integer = 20000
Que = New System.Collections.Queue(intQueSize)

Dim ipHostInfo As IPHostEntry = Dns.Resolve(HostName)
Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
socListener = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)
localEndPoint = New IPEndPoint(ipAddress, m_intPortNo)
End Sub

Public Sub Listen()
Dim intBLen As Integer
Dim bytes(1024) As Byte

Try
socListener.Bind(localEndPoint)
socClient = socListener.Accept()

While True
Try
intBLen = socClient.Receive(bytes)
Catch ex As Exception
Console.WriteLine("Listen:" & ex.Message)
End Try

If intBLen > 0 Then
Dim aryCopy(intBLen - 1) As Byte
Array.Copy(bytes, aryCopy, intBLen)
Que.Enqueue(aryCopy)
aryCopy = Nothing
End If

End While
Catch ex As Exception
Console.WriteLine("Listen:" & ex.Message)
End Try
End Sub

Public Sub Process()
Dim TempBuff() As String
Dim intBuffLen As Integer

Try
While True
TempBuff = Que.Dequeue()
intBuffLen = TempBuff.Length

'Note: The following portion of this function are array operation
(loop, copy, etc) to extract message for processing
End While
Catch ex As Exception
Console.WriteLine("Process:" & ex.Message)
End Try
End Sub

Thank you for your help.
 
P

Peter Duniho

newbie18 said:
Hi All,

I'm using almost the same approach as alexia in using Queue. However,
I'm not using any synchronize queue.

The sample code as follow has been running for about a year, but
recently I encounter "Object reference not set to an instance of an
object" error. Wondering would it be cause by the Queue. This error is
occurred at Process function in cSocket class. Please advise. [...]

I'm amazed the code worked at all.

The first thing it ought to do is throw an InvalidOperationException,
due to trying to dequeue an element from an empty queue. Specifically:
there is a very high likelihood of the receiving thread not getting a
chance to execute, adding something to the queue, before the original
thread gets into the cSocket.Process() method and tries to dequeue an
item. And that's not even counting the likelihood of the receiving
thread having to wait a bit for the first data to show up in the socket.

In other words, given the code shown, it should be quite common for the
Process() method to attempt to dequeue data from the queue before the
other thread has ever had a chance to enqueue any data. (And _that's_
not counting the lack of any synchronization/signaling, meaning that if
the receiving thread _ever_ falls behind the original thread processing
data, you should get an InvalidOperationException).

But even ignoring that issue, yes...you have no synchronization at all
in your code, and so your use of the queue is just as unsynchronized as
that found in alexia's code, and so can have the same problems,
including dequeuing a null reference.

Due to the lack of synchronization, you also have other potential
threading issues. For example, you have a class member, "socClient"
that is not protected by any synchronization, but which is not
initialized until the Listen() method starts to execute (and even there,
not right away). You also have an endless loop in your receive thread,
because you don't exit the loop when Receive() returns 0 (though, maybe
you get an exception, I don't recall off the top of my head...not the
best way to get out, but I suppose it's better than the thread hanging).

Basically, you've got multi-threaded code that hasn't got any proper
synchronization or thread-safety at all.

And on top of all that, you're asking about VB.NET code in a C#
newsgroup. :p

Pete
 
N

newbie18

First of all sorry to say that I didn't notice it is a C#
newsgroup. I just glad that I found something that related
what I'm working on.

Peter, thank you so much from your feedback even though I'm
in the wrong newsgroup.

Agree that I'm not handling well in threading and in the
code I'm provided, I have make a big mistake regarding
dequeue from empty queue and infinite loop when Receive. The
sample code that provides is a sub-set of my application,
therefore did such a big mistake when copy the code.

During the dequeue, actually I did check on queue count and
with thread sleep within the looping. With the queue count
checking, would it be possible to encounter the "Object
reference"? Since I'm in wrong newsgroup, where should I
route this question to. Thanks again.

Public Sub Listen()
Dim intBLen As Integer
Dim bytes(1024) As Byte

Try
socListener.Bind(localEndPoint)

waitClient:
If socClient is nothing Then
socClient.close()
End If

socClient = socListener.Accept()

While True
Try
intBLen = socClient.Receive(bytes)
Catch ex As Exception
Console.WriteLine("Listen:" & ex.Message)
End Try

If intBLen > 0 Then
Dim aryCopy(intBLen - 1) As Byte
Array.Copy(bytes, aryCopy, intBLen)
Que.Enqueue(aryCopy)
aryCopy = Nothing
Else
Goto waitClient
End If

End While
Catch ex As Exception
Console.WriteLine("Listen:" & ex.Message)
End Try
End Sub

Public Sub Process()
Dim TempBuff() As String
Dim intBuffLen As Integer

Try
While True
While Que.Count > 0
TempBuff = Que.Dequeue()
intBuffLen = TempBuff.Length

'Note: The following portion of this function are
array operation
(loop, copy, etc) to extract message for processing
End While

Threading.Thread.Sleep(2)
End While
Catch ex As Exception
Console.WriteLine("Process:" & ex.Message)
End Try
End Sub
 
P

Peter Duniho

newbie18 said:
[...]
During the dequeue, actually I did check on queue count and
with thread sleep within the looping. With the queue count
checking, would it be possible to encounter the "Object
reference"?

Without proper thread synchronization, if you can imagine a possible
incorrect outcome for your code, it could happen. That said, since we
already have someone else's example where a null reference is returned
for unsynchronized access to a Queue instance, it's safe to say yes,
that not only _could_ happen, but in fact it seems to be a not uncommon
way for the code to fail when used incorrectly.
Since I'm in wrong newsgroup, where should I
route this question to. Thanks again.

There is a general purpose .NET newsgroup --
microsoft.public.dotnet.framework -- that is language agnostic. There
is also a VB.NET-specific group, just like this C#-specific group. And
of course, you could always port your code to C# and continue to post
your questions here. :)

Regardless of what forum you choose, I will strongly advise that you
_not_ continue to use the Developersdex website. It's a lot of
overhead, plus it's difficult for you to use normal Usenet conventions
(such as quoting the relevant pieces of the post to which you're
replying). Get yourself a newsreader and just access the newsgroups
directly (if you don't have an ISP that provides NNTP access, the
microsoft.public.* hierarchy is available via Microsoft's own NNTP
server at news.microsoft.com).

Pete
 
N

newbie18

Hi Peter, thank you so much from your guidance.

I'm on my way in exploring NNTP which new to me and will start
make my posting from there.
 
Joined
Apr 12, 2010
Messages
1
Reaction score
0
Queue<T> Q enqueue dequeue instance object error.

I have an issue, that relates to the posted question and in C#. I have posted the full code, but the only method that generates an error is the last one GetQueue_Click(). The listboxes are properly formed on the main page, so it all has to do with the code behind. Any ideas why I can enqueue string[] but not dequeue it? Am I trying to dequeue too much?

using System; using System.Collections.Generic;

using System.IO; using System.Web.UI.HtmlControls;

using System.Security.Principal; using System.Data.SqlClient;


public
partial class TableImporter : System.Web.UI.Page
{

private const String DEAFULT_LISTITEM = "==NONE SELECTED==";

private const int USER = 0;

private const int FILE = 1;

private const int DATE = 2;

private const int SIZE = 3;

private Queue<String[]> Q_filepath;

private DateTime DT, pageLoadDT;

private String CrntDateTime, CrntUser, CrntFilepath;

private String[] sArray;

protected void Page_Load(object sender, EventArgs e)

{

MsgLabel.Text =
"";

CrntUser = System.Security.Principal.
WindowsIdentity.GetCurrent().Name.ToString();

MsgLabel.Text = CrntUser;

if (!this.IsPostBack)

{

pageLoadDT =
DateTime.Now;

UploadTable_ListBox.SelectedValue = DEAFULT_LISTITEM;

}

}

protected void UploadFile_Click(object sender, EventArgs e)

{

MsgLabel.Text = FileUpload1.FileName.ToString();

sArray =
new String[SIZE];

Q_filepath =
new Queue<String[]>();

if ((FileUpload1.HasFile) && (UploadTable_ListBox.SelectedValue.ToString().CompareTo(DEAFULT_LISTITEM)!=0))

{

DT =
DateTime.Now;

CrntDateTime = DT.ToString().Replace(
@"/", ".").Replace(" ", "_").Replace(":", "."); // m.d.yyyy

CrntFilepath = "~/UploadFiles/" + CrntUser + "_" + CrntDateTime + "_" +

UploadTable_ListBox.SelectedValue.ToString() +
".txt";

FileUpload1.SaveAs(MapPath(CrntFilepath));



sArray[USER] = CrntUser;

sArray[FILE] = CrntFilepath;

sArray[DATE] = CrntDateTime;

Q_filepath.Enqueue(sArray);

ListBox1.Items.Add(UploadTable_ListBox.SelectedValue.ToString()

+
" " + CrntDateTime + " " + CrntUser);

MsgLabel.Text =
"The last file, " + CrntFilepath + ", was submitted by " + CrntUser + ".";

}

else

{

MsgLabel.Text =
"Oops. The file was not uploaded. Both the file and the table must be selected.";

}

}

protected void ProcessUploadFiles_Click(object sender, EventArgs e)

{

}

protected void GetQueue_Click(object sender, EventArgs e)

{

while (Q_filepath.Peek()!=null)

{

String[] tArray = new String[SIZE];

tArray = Q_filepath.Dequeue();

QueContent_Listbox.Items.Add(tArray[USER] +
" ");

}

}

}

 

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