Tell a Task to wait until Timer has stopped

Logan B. Lehman

Explanation & Background: Sorry if this question sucks, but I am trying to wrap my head around Tasks. I currently have a set of classes that will take a control into their constructors, and allow for me to automate user interaction (typing into textbox, clicking button, etc.).

An example of one of these is my class called TextboxTester. Here is a snippet of how I bring in the textbox:

public class TextboxTester
{
    private int _currentTextLength = 0;
    private string _text;
    private TextBox _textBox;
    private Timer timer;

    #region Constructor
    public TextboxTester(TextBox TextBox)
    {
        _textBox = TextBox;
    }
    #endregion

I want to be able to chain actions(tasks) together in order - one after another so I can automate a series of user input events. I read up and found out about TPL tasks, and decided to give it a spin.

I created my TextboxTester class and my ButtonTester class, and passed in the controls. I want to be able to type into the textbox, and then click the button - so I call this:

Task.Factory.StartNew(() => txtTester.WriteText("Hello World")).Wait();
Task.Factory.StartNew(() => btnTester.Click(1));

From my knowledge of the Task.Factory calls, this is what I want to do - perform the first action, wait until it is done - and then perform the next. The problem is that TextboxTester.WriteText() uses a timer to emulate typing into a TextBox (1 character per second):

public void WriteText(string Text)
    {
        if (timer == null)
        {
            State.Working = true;
            timer = new Timer();

            try
            {
                _text = Text;
                timer.Elapsed += new ElapsedEventHandler(timer_ElapsedWrite);
                timer.Interval = 1000;
                timer.Enabled = true;
                timer.Start();
            }
            catch
            {
                MessageBox.Show("WriteText timer could not be started.");
            }
        }
    }
void timer_ElapsedWrite(object sender, ElapsedEventArgs e)
    {
        _textBox.Dispatcher.BeginInvoke(new Action(() =>
        {
            TextBoxAutomationPeer peer = new TextBoxAutomationPeer(_textBox);
            IValueProvider valueProvider = peer.GetPattern(PatternInterface.Value) as IValueProvider;
            valueProvider.SetValue(_text.Substring(0, _currentTextLength));

            if (_currentTextLength == _text.Length)
            {
                timer.Stop();
                State.Working = false;
                timer = null;
                return;
            }

            _currentTextLength++;

        }));
    }

**The _textBox.Dispatcher call in the elapsed event was to prevent a "thread already owns this object" message that was occurring.

Finally the problem: The Task.Factory.StartNew() call does not seem to take into account the time_elapsed event that is still occurring. I want to be able to finish out the events before the Task considers "WriteText" is complete.

and Question: Is there a way to tell a task to be able to take these types of things into account? Am I not understanding Tasks?

EDIT - I am using 3.5 and a 3.5 implementation of TPL

max

Right now you are getting no benefits from using tasks. Making WriteText an async method can make things much easier:

public async Task WriteText(string text)
{
    TextBoxAutomationPeer peer = new TextBoxAutomationPeer(_textBox);
    IValueProvider valueProvider = peer.GetPattern(PatternInterface.Value) as IValueProvider;
    for(int i = 1; i < text.Length; ++i)
    {
        await Task.Delay(1000); // no need for timer
        valueProvider.SetValue(text.Substring(0, i));
    }
}

So you can write

async void TestMethod()
{
   await txtTester.WriteText("Hello World"));
   Task.Factory.StartNew(() => btnTester.Click(1)); // probably sould be refactored too
}

Edit

Version without async/await with minimal changes to existing code:

public class TextboxTester
{
    /* unchanged code */

    // unfortunately, there is no non-generic version of this class
    // basically it allows us to 'manually' complete Task
    private TaskCompletionSource<object> _tcs;

    public Task WriteText(string Text)
    {
        if (timer == null)
        {
            _tcs = new TaskCompletionSource<object>();
            /* unchanged code */
        }
        return _tcs.Task; // return task which tracks work completion
    }

    /* unchanged code */
            if (_currentTextLength == _text.Length)
            {
                timer.Stop();
                State.Working = false;
                timer = null;
                _tcs.TrySetResult(null); // notify completion
                return;
            }
    /* unchanged code */
}

Now you can write

// well, you could simply make this a blocking method instead
txtTester.WriteText("Hello World").Wait();
btnTester.Click(1);

or better

txtTester.WriteText("Hello World")
         .ContinueWith(t => btnTester.Click(1)); // does not block calling thread

Main idea is to design your async method in a way which allows reporting completion. There are 3 common patterns for that:

  • Begin/End method pairs (BeginWriteText, which returns IAsyncResult and EndWriteText, which accepts IAsyncResult)
  • Event which is invoked when work is completed (public event EventHandler WriteTextCompleted)
  • Task-based approach (method returns Task)

These approaches are well described in Task-based Asynchronous Pattern

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

wait until Angular has finished loading issue

分類Dev

Java making the code wait until Swing-Timer finished work

分類Dev

React hooks - wait until the state has been updated

分類Dev

End background task and wait until app becomes active again - BLE processing data

分類Dev

Unable to resume timer at the time it was stopped

分類Dev

Cannot wait until DOM rendering has finished in Angular/Jasmine unit test

分類Dev

How do i add a firebase listener that would wait until firebase auth has loaded?

分類Dev

How do i add a firebase listener that would wait until firebase auth has loaded?

分類Dev

tomcat has been stopped

分類Dev

Gulp watch, wait for task

分類Dev

wait until scrollToRowAtIndexPath is done in swift

分類Dev

Wait until image dowloaded Firebase

分類Dev

Ansible to wait until connection is valid

分類Dev

Wait until a list of thread end

分類Dev

unfortunately,myapp has stopped working

分類Dev

Role has encountered an error and has stopped

分類Dev

How to tell shell command tail not to wait for parameter

分類Dev

Start task, later wait for completion

分類Dev

make JavaFX wait until Timeline finishes

分類Dev

How to wait until matplotlib animation ends?

分類Dev

How to wait until all NSOperations is finished?

分類Dev

Rxjs observable wait until some condition is met

分類Dev

How to use Driver Wait Until Text is in selenium

分類Dev

How to wait until specified keys will be pressed in NASM?

分類Dev

Wait until multiple request to be executed and their completion block

分類Dev

How to properly wait until future is complete in dart

分類Dev

How to wait until MSTSC.exe exits

分類Dev

Wait Until is not present, not working in Selenium C#

分類Dev

AJAX wait until file exist on another server

Related 関連記事

  1. 1

    wait until Angular has finished loading issue

  2. 2

    Java making the code wait until Swing-Timer finished work

  3. 3

    React hooks - wait until the state has been updated

  4. 4

    End background task and wait until app becomes active again - BLE processing data

  5. 5

    Unable to resume timer at the time it was stopped

  6. 6

    Cannot wait until DOM rendering has finished in Angular/Jasmine unit test

  7. 7

    How do i add a firebase listener that would wait until firebase auth has loaded?

  8. 8

    How do i add a firebase listener that would wait until firebase auth has loaded?

  9. 9

    tomcat has been stopped

  10. 10

    Gulp watch, wait for task

  11. 11

    wait until scrollToRowAtIndexPath is done in swift

  12. 12

    Wait until image dowloaded Firebase

  13. 13

    Ansible to wait until connection is valid

  14. 14

    Wait until a list of thread end

  15. 15

    unfortunately,myapp has stopped working

  16. 16

    Role has encountered an error and has stopped

  17. 17

    How to tell shell command tail not to wait for parameter

  18. 18

    Start task, later wait for completion

  19. 19

    make JavaFX wait until Timeline finishes

  20. 20

    How to wait until matplotlib animation ends?

  21. 21

    How to wait until all NSOperations is finished?

  22. 22

    Rxjs observable wait until some condition is met

  23. 23

    How to use Driver Wait Until Text is in selenium

  24. 24

    How to wait until specified keys will be pressed in NASM?

  25. 25

    Wait until multiple request to be executed and their completion block

  26. 26

    How to properly wait until future is complete in dart

  27. 27

    How to wait until MSTSC.exe exits

  28. 28

    Wait Until is not present, not working in Selenium C#

  29. 29

    AJAX wait until file exist on another server

ホットタグ

アーカイブ