From WikiChip
Difference between revisions of "mirc/thread"
< mirc

(/pause /sleep COM delayed script)
(/pause /sleep COM delayed script)
Line 57: Line 57:
  
 
<source lang="mIRC">
 
<source lang="mIRC">
 +
alias pause {
 +
  if ($1 !isnum 1-) return
 +
  var %a = $ticks $+ .vbs
 +
  write %a wscript.sleep $1
 +
  .comopen %a wscript.shell
 +
  if (!$comerr) .comclose %a $com(%a,Run,3,bstr,%a,uint,0,bool,true)
 +
  .remove %a
 +
}
 
alias mycode {
 
alias mycode {
 
   do something
 
   do something

Revision as of 05:21, 17 August 2018

This page aims to discuss threads in mIRC, delayed execution and non blocking while loop.

Thread

There are no thread in mIRC, mIRC is single threaded, always.

Sometimes it looks like mIRC can do multiple things at the same time without freezing, this is never the case, below we will discuss the different illusions that can occur.

mIRC's message loop

mIRC, just like many Windows applications, is based on a loop which processes messages, messages correspond to some kind of event, new data on a socket, a click on a button etc. For each iteration of the loop, one message only is processed and then the loop repeats.

This approach is what allows mIRC, or scripters to create the thread illusions.

Nested call to the message loop

The trick is to "call" the message loop yourself (you or mIRC, typically), handling one more message while the current one is running (nested execution) before returning to handling this current message

$input

mIRC itself, with $input, does this:

alias test {
  set %test 1
  noop $input(text,e)
  echo -a %test
}

When you call /test, the scripting engine has to wait for your input before processing the rest of the code, represented by an infinite while loop.

Just waiting for your input would freeze mirc since no others messages would be processed (how things usually works), so mIRC itself call the message loop once per iteration of that infinite while loop, and process more messages.

This can be demonstrated by running /test above, from a desktop window, (possibly with the 'u' switch of $input?) and then going back to mIRC and executing /set %test 2, when $input returns, 2 will be displayed, showing that $input allowed you to click back to mirc and running the scripting engine with /set, all of which are the result of handling the message loop

Whilefix Dll

For a very long time, a dll called whilefix.dll exists which will 'fix' your while loop in mIRC (pretty catchy isn't it?).

What this dll does is exactly what $input does, it calls the message loop and allow more message to be processed:

while (condition) {
  ;call the WhileFix routine
  dll path\to\whilefix.dll WhileFix
  your code here
}

And this loop will never freeze mIRC.

/pause /sleep COM delayed script

Since a very long time as well, COM script to pause the execution of your script exist (pausing can be done with timers, just not as handy):

alias pause {
  if ($1 !isnum 1-) return
  var %a = $ticks $+ .vbs
  write %a wscript.sleep $1
  .comopen %a wscript.shell
  if (!$comerr) .comclose %a $com(%a,Run,3,bstr,%a,uint,0,bool,true) 
  .remove %a
}
alias mycode {
  do something
  ;wait 5 second before continuing 
  pause 5
  do something else
}

This time it's Windows which is calling the message loop, mIRC does not know in advance which kind of COM you're using

Critical and non critical events

Ever wondered why you can't call $input from an on text event? This is related to the message loop.

All messages from the message loop which are related to sockets (scripted socket or mIRC's internal socket) can be called critical events whereas any other message (clicking on a nick in the nicklist for example) is considered a non critical event. Socket related messages are called critical because mIRC cannot handle these messages if they are handled from a nested call to the message loop. Indeed, imagine if the following were allowed:

on *:text:!test:#test:noop $input(test,e)
on *:text:*:#test:do stuff

If someone says !test on the channel, $input is called and as we saw above, mIRC will call the message loop until $input returns, now suppose a new message "test" is sent on the channel while your $input is running, since mIRC is processing the message loop, it would process this channel message and the second on text would trigger, this is not wanted, the first on text has to finish first to guarantee correct order of execution, this is why $input is not allowed in critical event, you can try to use $input inside mIRC's event to see if they are critical (as said only socket related events should return an error).

Danger

As we have seen, mIRC prevent you from using $input from critical event, but mIRC can't prevent you from using a dll which call the message loop (whilefix) or from using a COM delaying script.

on text