Multithreading 数码显微摄影下的线硕士
我在DigitalMicrograph中创建了两个线程,它们将在脚本执行后立即执行。Multithreading 数码显微摄影下的线硕士,multithreading,dm-script,Multithreading,Dm Script,我在DigitalMicrograph中创建了两个线程,它们将在脚本执行后立即执行。 我想要一些不同的东西 让我们设想两个线程按钮(开始和停止线程)。 如何添加代码以仅在按下按钮时激活线程 如果您能为我提供一个代码示例,那将非常有帮助。有几件事需要考虑: 不能从UIframe对象中分配新对象。(更准确地说:通过UI操作调用的方法。您可以在构造函数中或在开始时使用Init()方法分配f.e。)因此,您可以预先分配它们,然后让UIframe对象知道它们 您通常希望UIframe对象了解线程对象,但
我想要一些不同的东西 让我们设想两个线程按钮(开始和停止线程)。
如何添加代码以仅在按下按钮时激活线程
如果您能为我提供一个代码示例,那将非常有帮助。有几件事需要考虑:
- 不能从UIframe对象中分配新对象。(更准确地说:通过UI操作调用的方法。您可以在构造函数中或在开始时使用Init()方法分配f.e。)因此,您可以预先分配它们,然后让UIframe对象知道它们
- 您通常希望UIframe对象了解线程对象,但也希望thread对象了解UIframe对象。(这样,如果线程对象中的某些内容需要,UI可以更改。)
- 将对象作为对象的成员变量有点危险,因为只有在将“keeping”对象释放到后才能释放这些对象。如果两个对象以成员变量的形式相互持有,则处于死锁状态!因此,使用弱引用是可取的:只保留objectID编号作为成员变量,并根据需要查找对象
class myThread:Thread
{
number linkedDLG_ID
number externalBreak
myThread( object self )
{
result( self.ScriptObjectGetID() + " created.\n" )
}
~myThread( object self )
{
result( self.ScriptObjectGetID() + " destroyed.\n" )
}
void SetLinkedDialogID( object self, number ID ) { linkedDLG_ID = ID; }
void InterruptAtNextChance( object self ) { externalBreak = 1; }
void RunThread( object self )
{
number maxLoop = 30
object callDLG = GetScriptObjectFromID( linkedDLG_ID )
externalBreak = 0
for( number i=0; i<maxLoop; i++ )
{
sleep( 0.1 )
Result( i + "\n" )
if ( callDLG.ScriptObjectIsValid() )
{
callDLG.DLGSetProgress( "progress", (i+1)/maxLoop )
callDLG.ValidateView()
}
if ( externalBreak )
break;
}
// Cleanup at end of thread
if ( callDLG.ScriptObjectIsValid() )
{
callDLG.DLGSetProgress( "progress", 0 )
callDLG.LookUpElement( "DBevel" ).DLGValue( 0 )
callDLG.ValidateView( )
}
}
}
class myDialog:UIframe
{
object callThread
myDialog( object self )
{
result( self.ScriptObjectGetID() + " created.\n" )
}
~myDialog( object self )
{
result( self.ScriptObjectGetID() + " destroyed.\n")
}
TagGroup CreateDLG( object self )
{
image i := IntegerImage( "", 1, 0, 25, 25)
i = 0; i[ 2 , 2 , 23 , 23 ] = 1;
image onImage, offImage
onImage = RGB( 0*i , 200*i , 0*i )
offImage = RGB( 200*i , 0*i , 0*i )
TagGroup tgItems, tg, button, label, progress
tg = DLGCreateDialog("Dialog",tgItems)
button = DLGCreateDualStateBevelButton( "DBevel", onImage, offImage, "StartPressed" )
progress = DLGCreateProgressBar( "progress" ).DLGfill( "X" )
label = DLGCreateLabel( "start/stop" )
tgItems.DLGAddElement( DLGGroupItems( button , label ).DLGTableLayout( 2 , 1 , 0 ) )
tgItems.DLGAddElement( progress )
return tg
}
object Init(object self, number callThreadID )
{
// Assign thread-object via weak-reference
callThread = GetScriptObjectFromID( callThreadID )
if ( !callThread.ScriptObjectIsvalid() )
Throw( "Invalid thread object passed in! Object of given ID not found." )
// Pass weak-reference to thread object
callThread.SetLinkedDialogID( self.ScriptObjectGetID() )
return self.super.init( self.CreateDLG() )
}
void StartPressed( object self )
{
number active = self.LookupElement( "DBevel" ).DLGGetValue()
if ( active )
callThread.StartThread()
else
callThread.InterruptAtNextChance()
}
}
void StartScript()
{
object threadObject = alloc( myThread )
object dlgObject = alloc( myDialog ).Init( threadObject.ScriptObjectGetID() )
dlgObject.display( "Dialog" )
}
StartScript()
- 任何对话框(UI)类都是从UIframe类派生的
- 这个类只有一个成员变量:一个对象,它将是thread对象
- 同样,还有一个构造函数/析构函数方法,以便于调试
- CreateDLG方法构建描述对话框的标记组。我将不在这里详细介绍,但它在显示时会创建以下对话框:
- Init()方法初始化对象。基类UIframe的Init()方法需要一个描述性标记组,并返回UI对象本身。我们在extended Init()方法的最后一行调用它,并使用class方法创建标记组:
前面的代码将线程对象链接到UI对象。我们传入一个数字,它是线程对象的对象ID。现在,我们从内存中获取相应的对象,并将其分配给本地成员变量。(注意:变量现在保存对象本身,而不是对象的副本或克隆!)返回self.super.init(self.CreateDLG())
我们立即检查查找是否成功并实际返回了有效对象。如果没有,我们将使用抛出的异常停止脚本。从现在起,UI对象“包含”线程对象并可以使用它callThread=GetScriptObjectFromID(callThreadID)
- 现在返回链接。既然已经分配了UI对象,它也有了一个object-ID。我们将这个数字输入到我们的thread对象中
从现在起,thread对象将很好地链接到UI对象。回顾myThread类,您会注意到我们使用了相同的技巧,在callThread.SetLinkedDialogID(self.ScriptObjectGetID())
方法中查找并本地存储对象RunThread()
- StartPressed()是链接到对话框按钮的方法。这个按钮是一个斜面按钮,所以我们查询它的状态,即斜面按钮更改后的状态,并相应地进行操作。我们要么启动线程对象的RunThread()方法作为后台线程,要么调用相应的“interrupt”方法,该方法只设置布尔变量
class myThread:Thread
{
number linkedDLG_ID
number externalBreak
myThread( object self )
{
result( self.ScriptObjectGetID() + " created.\n" )
}
~myThread( object self )
{
result( self.ScriptObjectGetID() + " destroyed.\n" )
}
void SetLinkedDialogID( object self, number ID ) { linkedDLG_ID = ID; }
void InterruptAtNextChance( object self ) { externalBreak = 1; }
void RunThread( object self )
{
number maxLoop = 30
object callDLG = GetScriptObjectFromID( linkedDLG_ID )
externalBreak = 0
for( number i=0; i<maxLoop; i++ )
{
sleep( 0.1 )
Result( i + "\n" )
if ( callDLG.ScriptObjectIsValid() )
{
callDLG.DLGSetProgress( "progress", (i+1)/maxLoop )
callDLG.ValidateView()
}
if ( externalBreak )
break;
}
// Cleanup at end of thread
if ( callDLG.ScriptObjectIsValid() )
{
callDLG.DLGSetProgress( "progress", 0 )
callDLG.LookUpElement( "DBevel" ).DLGValue( 0 )
callDLG.ValidateView( )
}
}
}
class myDialog:UIframe
{
object callThread
myDialog( object self )
{
result( self.ScriptObjectGetID() + " created.\n" )
}
~myDialog( object self )
{
result( self.ScriptObjectGetID() + " destroyed.\n")
}
TagGroup CreateDLG( object self )
{
image i := IntegerImage( "", 1, 0, 25, 25)
i = 0; i[ 2 , 2 , 23 , 23 ] = 1;
image onImage, offImage
onImage = RGB( 0*i , 200*i , 0*i )
offImage = RGB( 200*i , 0*i , 0*i )
TagGroup tgItems, tg, button, label, progress
tg = DLGCreateDialog("Dialog",tgItems)
button = DLGCreateDualStateBevelButton( "DBevel", onImage, offImage, "StartPressed" )
progress = DLGCreateProgressBar( "progress" ).DLGfill( "X" )
label = DLGCreateLabel( "start/stop" )
tgItems.DLGAddElement( DLGGroupItems( button , label ).DLGTableLayout( 2 , 1 , 0 ) )
tgItems.DLGAddElement( progress )
return tg
}
object Init(object self, number callThreadID )
{
// Assign thread-object via weak-reference
callThread = GetScriptObjectFromID( callThreadID )
if ( !callThread.ScriptObjectIsvalid() )
Throw( "Invalid thread object passed in! Object of given ID not found." )
// Pass weak-reference to thread object
callThread.SetLinkedDialogID( self.ScriptObjectGetID() )
return self.super.init( self.CreateDLG() )
}
void StartPressed( object self )
{
number active = self.LookupElement( "DBevel" ).DLGGetValue()
if ( active )
callThread.StartThread()
else
callThread.InterruptAtNextChance()
}
}
void StartScript()
{
object threadObject = alloc( myThread )
object dlgObject = alloc( myDialog ).Init( threadObject.ScriptObjectGetID() )
dlgObject.display( "Dialog" )
}
StartScript()
- 这里发生的事情不多。我们首先创建myThread类的Thread对象,然后创建dialog UI对象
- 我们使用现有threadObject的ID初始化dialog对象,然后将其显示为无模式对话框
class myThread:Thread
{
number linkedDLG_ID
number externalBreak
myThread( object self )
{
result( self.ScriptObjectGetID() + " created.\n" )
}
~myThread( object self )
{
result( self.ScriptObjectGetID() + " destroyed.\n" )
}
void SetLinkedDialogID( object self, number ID ) { linkedDLG_ID = ID; }
void InterruptAtNextChance( object self ) { externalBreak = 1; }
void RunThread( object self )
{
number maxLoop = 30
object callDLG = GetScriptObjectFromID( linkedDLG_ID )
externalBreak = 0
for( number i=0; i<maxLoop; i++ )
{
sleep( 0.1 )
Result( i + "\n" )
if ( callDLG.ScriptObjectIsValid() )
{
callDLG.DLGSetProgress( "progress", (i+1)/maxLoop )
callDLG.ValidateView()
}
if ( externalBreak )
break;
}
// Cleanup at end of thread
if ( callDLG.ScriptObjectIsValid() )
{
callDLG.DLGSetProgress( "progress", 0 )
callDLG.LookUpElement( "DBevel" ).DLGValue( 0 )
callDLG.ValidateView( )
}
}
}
class myDialog:UIframe
{
object callThread
myDialog( object self )
{
result( self.ScriptObjectGetID() + " created.\n" )
}
~myDialog( object self )
{
result( self.ScriptObjectGetID() + " destroyed.\n")
}
TagGroup CreateDLG( object self )
{
image i := IntegerImage( "", 1, 0, 25, 25)
i = 0; i[ 2 , 2 , 23 , 23 ] = 1;
image onImage, offImage
onImage = RGB( 0*i , 200*i , 0*i )
offImage = RGB( 200*i , 0*i , 0*i )
TagGroup tgItems, tg, button, label, progress
tg = DLGCreateDialog("Dialog",tgItems)
button = DLGCreateDualStateBevelButton( "DBevel", onImage, offImage, "StartPressed" )
progress = DLGCreateProgressBar( "progress" ).DLGfill( "X" )
label = DLGCreateLabel( "start/stop" )
tgItems.DLGAddElement( DLGGroupItems( button , label ).DLGTableLayout( 2 , 1 , 0 ) )
tgItems.DLGAddElement( progress )
return tg
}
object Init(object self, number callThreadID )
{
// Assign thread-object via weak-reference
callThread = GetScriptObjectFromID( callThreadID )
if ( !callThread.ScriptObjectIsvalid() )
Throw( "Invalid thread object passed in! Object of given ID not found." )
// Pass weak-reference to thread object
callThread.SetLinkedDialogID( self.ScriptObjectGetID() )
return self.super.init( self.CreateDLG() )
}
void StartPressed( object self )
{
number active = self.LookupElement( "DBevel" ).DLGGetValue()
if ( active )
callThread.StartThread()
else
callThread.InterruptAtNextChance()
}
}
void StartScript()
{
object threadObject = alloc( myThread )
object dlgObject = alloc( myDialog ).Init( threadObject.ScriptObjectGetID() )
dlgObject.display( "Dialog" )
}
StartScript()
- 无论何时在DigitalMicrograph脚本中使用对象变量,都应该将它们放入结构块中。这样可以确保在保留结构块时,对象超出范围并被删除。在主脚本中定义和分配的对象变量不会在脚本末尾被销毁。因此,我们将主脚本封装在方法本身中
- 在本例中,我们使用了两种不同的链接方法:
- Direct:myDialog类实际上将thread对象本身保留为成员变量。尽管我们仅使用ID初始化它,但我们立即将对象链接到一个成员变量
- 弱引用:myThread类仅将对话框对象的对象ID作为成员变量保存
- 我们创建线程对象
- 我们创建对话框对象
- 我们显示对话框对象(但我们不会在这里停止脚本执行!)
- 脚本结束 但是当脚本结束时,对象变量threadObject和dlgObject将超出范围!除非有什么东西把它们保存在内存中,否则它们会立即被销毁。dlgObject保留在内存中,因为我们将其显示为无模式对话框。当相应的对话框窗口关闭时,它将被释放。但是是什么让threadObjec