-1

I am working on a small tool that works in the following way:

  • show a series of images
  • after each image, show an answer window, where the user inputs the answer by pressing a button on the keyboard
  • the answer window is shown only for X seconds, after which it disappears, treating the question unanswered

What i did, was i made a class, that extends UserControl

public partial class AnswerDialog : UserControl
{
    ...

    public void ShowAnswerDialog()
    {
        ResponseItemType = Settings.ItemType.ObjectType_NONE;
        this.Show();
        allowAnswer = true;
    }

    public void HideAnswerDialog()
    {
        allowAnswer = false;
        this.Hide();
    }

    ...

    private void buttonAnswerItemType0_Click(object sender, EventArgs e)
    {
        SetAnswer(Settings.ItemType.ObjectType_0);
    }

    private void buttonAnswerItemType1_Click(object sender, EventArgs e)
    {
        SetAnswer(Settings.ItemType.ObjectType_1);
    }

    public void AnswerDialog_KeyDown(object sender, KeyEventArgs e)
    {
        if (Settings.KeyCodeAnswer0 == e.KeyCode)
        {
            SetAnswer(Settings.ItemType.ObjectType_0);
        }
        else if (Settings.KeyCodeAnswer1 == e.KeyCode)
        {
            SetAnswer(Settings.ItemType.ObjectType_1);
        }
    }

    ...
}

It receives the keyboard events from the parent from.

I have a class, where i control this sequence of showing the images and recording the results. In this class, i have the following function:

void AnswerThreadFunc(Object Param)
{
    AnswerDialog answerDialog = (AnswerDialog)Param;
    answerDialog.ShowAnswerDialog();
}

I did it this way, so i can timeout this thread in the main thread:

Thread answerThread = new Thread(AnswerThreadFunc); //create thread

answerThread.Start(_testWindow.GetAnswerDialog()); //run thread

answerThread.Join(Settings.DurationResponseMs); //wait for thread with timout
_testWindow.GetAnswerDialog().HideAnswerDialog(); //hide if window remained

Settings.ItemType response = _testWindow.GetAnswerDialog().ResponseItemType;
item.GiveResponse(response);

But this will throw the following exception:

Exception thrown: 'System.InvalidOperationException' in System.Windows.Forms.dll An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll Cross-thread operation not valid: Control 'panelMainControl' accessed from a thread other than the thread it was created on.

Thanks you.

user2281752
  • 145
  • 1
  • 9

1 Answers1

1

The error message will give you a lot of hits if you search it, but it tells no lies; only the thread that created a winforms control may interact with it. Controls even have a property that will tell you if you're on the right thread or not (InvokeRequired) and searching on this will return a raft of info of how to find out if youre on the wrong thread and how to call to the right thread to do the work..

But.. I think you've over complicated this. It can all be done on the original UI thread with a Timer- show the window and start the timer, if the window hides, stop the timer (attach to a suitable event on the answer window to know if it has hidden - probably VisibleChanged, but possibly FormClosing/ed). If the timer tick event fires after the timer Delay of 3 seconds, hide the window

Edit: actually, simpler the having the main window watch for the hiding of the answer window: have the answer window contain a timer that closes the answer window after 3 seconds, start the timer in form load/show/whatever. Any one of the answer buttons also closes the window. ShowDialog it- one of two things happen- either user uses a button and the window closes and an answer is set, or the timer closes it and no answer is set. After showdialog, retrieve the answer Property, which will either be set or not. If you want to use the timer to give the user an indication of how much time thy have left, set its interval to 100, and have an int count down from 30 in the timer tick. When the int hits 0 close the answer window. Put int/10.0 in a label as a count down timer

No need for multi threading here

Caius Jard
  • 72,509
  • 5
  • 49
  • 80